From baa0b5f3a990a4bb004194269d6e8cc67c6fea8b Mon Sep 17 00:00:00 2001 From: Degradin Date: Sun, 8 Oct 2023 23:43:12 +0300 Subject: [PATCH] global refactoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Все переведено в модули --- bot.js | 407 +++ commands/admin/createPromo.js | 29 + commands/admin/fastblock.js | 23 + commands/admin/genPromo.js | 36 + commands/admin/reportAnswer.js | 26 + commands/bonus.js | 89 + commands/carcantainers/chooseContainer.js | 32 + commands/carcantainers/containersMenu.js | 30 + commands/casino/casinoMenu.js | 13 + commands/casino/slots.js | 68 + commands/casino/slotsMenu.js | 30 + commands/erase.js | 67 + commands/getprofile.js | 33 + commands/index.js | 40 + commands/invite.js | 49 + commands/jobs/chooseJob.js | 96 + commands/jobs/jobs.js | 36 + commands/jobs/work.js | 191 ++ commands/menu.js | 15 + commands/organization/invite.js | 38 + commands/organization/inviteAction.js | 34 + commands/organization/leaveOrg.js | 41 + commands/organization/leaveOrgAccept.js | 28 + commands/organization/materialsBuy.js | 29 + commands/organization/orgMessage.js | 24 + commands/organization/organizationCreate.js | 45 + commands/organization/organizationMenu.js | 57 + commands/organization/payday.js | 70 + commands/organization/percentSet.js | 34 + commands/organization/workoff.js | 71 + commands/pay.js | 35 + commands/profile.js | 32 + commands/promocodeActivate.js | 34 + commands/property/hatkeisList.js | 18 + commands/property/propertyBuy.js | 102 + commands/property/propertyList.js | 42 + commands/property/propertyMenu.js | 19 + commands/property/propertySell.js | 102 + commands/report.js | 31 + commands/scratch.js | 7 + commands/top.js | 30 + commands/world.js | 12 + config/imports.js | 48 + config/index.js | 26 + ctxconfig.json | 14 + ecosystem.config.js | 15 + handlers/catch.js | 54 + handlers/index.js | 3 + index backup.js | 1763 +++++++++++++ index.js | 1763 +------------ json/fastlog.json | 2460 +++++++++++++++++++ json/rarecars.json | 5 + json/simplecars.json | 5 + json/weaponshop.json | 45 +- media/Thumbs.db | Bin 0 -> 6144 bytes media/image.png | Bin 120075 -> 120358 bytes package-lock.json | 1512 +++++++++++- package.json | 2 + run.ps1 | 2 + scenes/crime.js | 56 + scenes/heist.js | 56 + scenes/index.js | 17 + scenes/test.js | 40 + utils/escape.js | 22 + utils/generatePromo.js | 37 + utils/generateVoucher.js | 28 + utils/getCurrentTime.js | 10 + utils/getSlot.js | 22 + utils/giveExp.js | 20 + utils/html-escape.js | 10 + utils/index.js | 33 + utils/matPriceUpdate.js | 11 + utils/rand.js | 3 + utils/random.js | 7 + utils/setCooldown.js | 26 + utils/spaces.js | 4 + utils/spacesV2.js | 4 + utils/stats.js | 61 + utils/weaponShopUpdate.js | 28 + 79 files changed, 8665 insertions(+), 1792 deletions(-) create mode 100644 bot.js create mode 100644 commands/admin/createPromo.js create mode 100644 commands/admin/fastblock.js create mode 100644 commands/admin/genPromo.js create mode 100644 commands/admin/reportAnswer.js create mode 100644 commands/bonus.js create mode 100644 commands/carcantainers/chooseContainer.js create mode 100644 commands/carcantainers/containersMenu.js create mode 100644 commands/casino/casinoMenu.js create mode 100644 commands/casino/slots.js create mode 100644 commands/casino/slotsMenu.js create mode 100644 commands/erase.js create mode 100644 commands/getprofile.js create mode 100644 commands/index.js create mode 100644 commands/invite.js create mode 100644 commands/jobs/chooseJob.js create mode 100644 commands/jobs/jobs.js create mode 100644 commands/jobs/work.js create mode 100644 commands/menu.js create mode 100644 commands/organization/invite.js create mode 100644 commands/organization/inviteAction.js create mode 100644 commands/organization/leaveOrg.js create mode 100644 commands/organization/leaveOrgAccept.js create mode 100644 commands/organization/materialsBuy.js create mode 100644 commands/organization/orgMessage.js create mode 100644 commands/organization/organizationCreate.js create mode 100644 commands/organization/organizationMenu.js create mode 100644 commands/organization/payday.js create mode 100644 commands/organization/percentSet.js create mode 100644 commands/organization/workoff.js create mode 100644 commands/pay.js create mode 100644 commands/profile.js create mode 100644 commands/promocodeActivate.js create mode 100644 commands/property/hatkeisList.js create mode 100644 commands/property/propertyBuy.js create mode 100644 commands/property/propertyList.js create mode 100644 commands/property/propertyMenu.js create mode 100644 commands/property/propertySell.js create mode 100644 commands/report.js create mode 100644 commands/scratch.js create mode 100644 commands/top.js create mode 100644 commands/world.js create mode 100644 config/imports.js create mode 100644 config/index.js create mode 100644 ctxconfig.json create mode 100644 ecosystem.config.js create mode 100644 handlers/catch.js create mode 100644 handlers/index.js create mode 100644 index backup.js create mode 100644 json/fastlog.json create mode 100644 media/Thumbs.db create mode 100644 run.ps1 create mode 100644 scenes/crime.js create mode 100644 scenes/heist.js create mode 100644 scenes/index.js create mode 100644 scenes/test.js create mode 100644 utils/escape.js create mode 100644 utils/generatePromo.js create mode 100644 utils/generateVoucher.js create mode 100644 utils/getCurrentTime.js create mode 100644 utils/getSlot.js create mode 100644 utils/giveExp.js create mode 100644 utils/html-escape.js create mode 100644 utils/index.js create mode 100644 utils/matPriceUpdate.js create mode 100644 utils/rand.js create mode 100644 utils/random.js create mode 100644 utils/setCooldown.js create mode 100644 utils/spaces.js create mode 100644 utils/spacesV2.js create mode 100644 utils/stats.js create mode 100644 utils/weaponShopUpdate.js diff --git a/bot.js b/bot.js new file mode 100644 index 0000000..babc871 --- /dev/null +++ b/bot.js @@ -0,0 +1,407 @@ +require('dotenv').config() +const { + Telegraf, + Scenes, + session, + Stage, + Markup +} = require('telegraf') +const { + weaponshop, + slots, + rarecars, + simplecars, + houses, + cars, + phones, + weapons, + equipment, + UserModel, + WorldModel, + JobModel, + PropertyModel, + BusinessModel, + ReportModel, + BlockModel, + PromocodeModel, + mainChat, + adminList, + expToUp, + topSym +} = require('./config') +const { + profile, + bonus, + pay, + getprofile, + menu, + worldMenu, + referal, + jobs, + chooseJob, + casinoMenu, + work, + top, + propertyList, + propertyMenu, + propertyBuy, + propertySell, + hatkeisList, + organizationMenu, + workoff, + leaveOrg, + leaveOrgAccept, + payday, + orgMessage, + materialsBuy, + percentSet, + invite, + inviteAction, + report, + slotsMenu, + slotsRun, + promocodeActivate, + carContainers, + chooseContainer, + reportAnswer, + fastblock, + createPromo, + genPromo, + organizationCreate +} = require('./commands') +const { + spaces, + spacesWithMarkdown, + escape, + generatePromo, + generateVoucher, + getCurrentTime, + getSlot, + giveExp, + matPriceUpdate, + rand, + random, + setCooldown, + weaponShopUpdate, + stats +} = require('./utils') +const { + handleError + } = require('./handlers') +const crimeScene = require("./scenes/crime"); +const heistScene = require("./scenes/heist"); +const sequelize = require('./db'); +const { Op } = require('sequelize'); +const fs = require('fs'); +const { createCanvas, loadImage } = require('canvas'); +const shortid = require('shortid'); +const voucher_codes = require('voucher-code-generator'); +const bot = new Telegraf(process.env.BOT_TOKEN) +const stage = new Scenes.Stage([crimeScene, heistScene]); + +const start = async () => { + try { + await sequelize.authenticate() + await sequelize.sync() + } catch (e) { + console.log('Подключение к бд сломалось', e) + } +} + +bot.telegram.setMyCommands([{ + command: "pay", + description: "Перевести указанному пользователю сумму." + }, + { + command: "buy", + description: "Приобрести указанное имущество." + }, + { + command: "business", + description: "Создать организацию." + }, + { + command: "invite", + description: "Пригласить пользователя в организацию." + }, + { + command: "percent", + description: "Установить пользователю процент заработка." + }, + { + command: "report", + description: "Создать жалобу/обращение/идею." + } +]) + +bot.use(session({ collectionName: 'sessions' })); +bot.use(stage.middleware()) +bot.use(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(getCurrentTime() + `: ` + username + `: ` + ctx.update.message.text) + break; + case `callback_query`: + console.log(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); + 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 + }) + } else {} + //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.scene.enter('Crime') +}) + + +bot.hears('промка', async(ctx) => { + generatePromo() +}); + +bot.hears('▶️ Меню', menu); + +bot.hears('Чат', async (ctx) => { + ctx.reply(`${ctx.message.chat.id}`) +}); + +bot.hears('😎 Профиль', profile); + +bot.command('getprofile', 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('🎁 Бонус', bonus) + +bot.command('pay', pay) + +bot.hears('Мир', worldMenu) + +bot.hears('📞 Пригласить', referal) + +bot.hears('📢 Вакансии', jobs) + +bot.action(/job_(1|2|3|4|5|6|7|leave)/, chooseJob) + +bot.hears('🏯 Казино', casinoMenu) + +bot.hears('🗄️ Работать', work) + +bot.hears('Топ', top) + +bot.hears('🔵 Имущество', propertyMenu) + +bot.action('shopmenu', propertyMenu) + +bot.action(/shop_(house|phone|car)/, propertyList) + +bot.action(/{"action": "buy"*/, propertyBuy) + +bot.hears('Поставщик', hatkeisList) + +bot.command('sell', propertySell) + +bot.hears('🌐 Организация', organizationMenu) + +bot.action('workoff', workoff) + +bot.action('покинуть', leaveOrg) + +bot.action('cancel', async (ctx) => { + await ctx.deleteMessage() + await bot.telegram.answerCbQuery(ctx.callbackQuery.id, `Отмена.`) +}) + +bot.action('user_leave_business', leaveOrgAccept) + +bot.action('payday', payday) + +bot.command('orgmessage', orgMessage) + +bot.command('materials', materialsBuy) + +bot.command('percent', percentSet) + +bot.command('business', organizationCreate) + +bot.command('invite', invite) + +bot.action(/{"type": "business_invite_(accept|refuse)"*/, inviteAction) + +bot.command('report', report) + +bot.hears('🎰 Слоты', slotsMenu) + +bot.action(/slots(1000|5000|25000|50000|100000)/, 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', promocodeActivate) + +bot.hears('📦 Контейнеры', carContainers) + +bot.action(/container_(1|2|3|4|5|6|7|8|9|10)/, 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() +}) +/////////////////////////////////////Admin Commands////////////////////////////////////////////////// + + +bot.command('answer', reportAnswer) + +bot.command('fastblock', fastblock) + +bot.command('createpromocode', createPromo) + +bot.command('genpromo', genPromo) + +///////////////////////////////////////Functions////////////////////////////////////////////////////// + +setInterval(() => { + generatePromo() +}, 18000000); + +setInterval(() => { + var today = new Date(); + let hours = today.getHours(); + if (hours == "0" || hours == "12") { + weaponShopUpdate() + matPriceUpdate() + } +}, 360000); + +start() + +bot.launch() \ No newline at end of file diff --git a/commands/admin/createPromo.js b/commands/admin/createPromo.js new file mode 100644 index 0000000..c357f71 --- /dev/null +++ b/commands/admin/createPromo.js @@ -0,0 +1,29 @@ +const { + UserModel, + PromocodeModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + generateVoucher +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if(user.status != 'admin') return await ctx.reply(`Admin Only.`) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1] || !ctx.args[2] || !ctx.args[3]) return ctx.reply(`/createpromo [activations] [money] [code]`) + let promocode = await PromocodeModel.findOne({ + where: { + code: ctx.args[3] + } + }) + if(promocode === null){ + await PromocodeModel.create({ + code: ctx.args[3], + activations: ctx.args[1], + money: ctx.args[2] + }) + let voucherImage = await generateVoucher(ctx.args[3], ctx.args[1], ctx.args[2]) + console.log(voucherImage) + return await ctx.sendPhoto({source: voucherImage, caption: `Создан промокод ${ctx.args[3]}` }) +} +} \ No newline at end of file diff --git a/commands/admin/fastblock.js b/commands/admin/fastblock.js new file mode 100644 index 0000000..0612a34 --- /dev/null +++ b/commands/admin/fastblock.js @@ -0,0 +1,23 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + BlockModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if(!ctx.message.reply_to_message) return await ctx.reply(`Только на пересланное сообщение.`) + let blocked = ctx.message.reply_to_message.from.id + 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(`Пользователь заблокирован.`) +} \ No newline at end of file diff --git a/commands/admin/genPromo.js b/commands/admin/genPromo.js new file mode 100644 index 0000000..8206e83 --- /dev/null +++ b/commands/admin/genPromo.js @@ -0,0 +1,36 @@ +const voucher_codes = require('voucher-code-generator'); +const { + UserModel, + PromocodeModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + generateVoucher +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if(user.status != 'admin') return await ctx.reply(`Admin Only.`) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`/genpromo [activations] [money]`) + let code = voucher_codes.generate({ + length: 6, + count: 1, + prefix: "CMP-", + postfix: "-FIRE", + charset: voucher_codes.charset("alphanumeric") + }); + let promocode = await PromocodeModel.findOne({ + where: { + code: code[0] + } + }) + if(promocode === null){ + await PromocodeModel.create({ + code: code[0], + activations: ctx.args[1], + money: ctx.args[2] + }) + let voucherImage = await generateVoucher(code, ctx.args[1], ctx.args[2]) + return await ctx.sendPhoto({source: voucherImage, caption: `Создан промокод ${code[0]}` }) +} +} \ No newline at end of file diff --git a/commands/admin/reportAnswer.js b/commands/admin/reportAnswer.js new file mode 100644 index 0000000..0bfc1fb --- /dev/null +++ b/commands/admin/reportAnswer.js @@ -0,0 +1,26 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + ReportModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if(user.status != 'admin') return await ctx.reply(`Admin Only.`) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1]) return ctx.reply(`Нужен номер обращения`) + let report = await ReportModel.findByPk(ctx.args[1]) + if (report === null) return await ctx.reply(`Нет обращения с таким ID.`) + if (report.status == 0) return await ctx.reply(`Данное обращение уже закрыто.`) + let answer = ctx.args + answer.shift() + answer.shift() + answer = answer.join(' ') + await bot.telegram.sendMessage(report.author, `Ответ на обращение #${report.id}[${report.uid}]\n\n` + answer) + report.status = 0 + report.save() + return await ctx.reply(`Ответ отправлен, обращение закрыто!`) +} \ No newline at end of file diff --git a/commands/bonus.js b/commands/bonus.js new file mode 100644 index 0000000..22fd602 --- /dev/null +++ b/commands/bonus.js @@ -0,0 +1,89 @@ +const { + UserModel, + WorldModel, + BusinessModel +} = require('../config') +const { + rand, + setCooldown +} = require('../utils') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + if (!user) return ctx.reply(`Ошибка #1`); + let bonustime = user.bonustime + let cooldown = setCooldown(user, 3600, bonustime) + if (user.bonustime > cooldown.currentTime) return ctx.reply(`📛 Забрать бонус можно будет через ${cooldown.timeLeftInMinutes} минут(у/ы)`); + user.bonus = 1; + user.bonustime = cooldown.endTime + let world = await WorldModel.findByPk(1) + let text = ``; + let money = [100, 200, 300, 400, 500, 1000].random(); + if (user.level >= 5) { + money += money; + } + let r = rand(1, 2); + let x = rand(2, 7); + if (r == 1) { + text += `⏩ ₽${money}\n`; + } + if (r == 2) { + money = money*x + text += `⏩ ₽${money}\n`; + } + switch(user.status){ + case 'bronze': + user.money += 5000 + text += `⭐ Дополнительный бонус за Bronze:\n⏩ ₽5.000\n` + break; + case 'silver': + user.money += 15000 + text += `⭐ Дополнительный бонус за Silver:\n⏩ ₽15.000\n` + break; + case 'gold': + user.money += 30000 + text += `⭐ Дополнительный бонус за Gold:\n⏩ ₽30.000\n` + break; + } + user.money += money; + world.balance -= money + if (user.business.id == 0){ + await user.save(); + await world.save(); + return ctx.reply(` + ⭐ Из ежечасного бонуса Вам выпало: +${text} + `) + } + let business = await BusinessModel.findOne({ + where: { + owner: user.business.id.toString() + } + }) + if(business != null){ + let mats = rand(3, 10) + switch(user.status){ + case 'bronze': + business.materials += 5 + text += `⭐ Дополнительный бонус за Bronze:\n⏩ 5 материалов\n` + break; + case 'silver': + business.materials += 10 + text += `⭐ Дополнительный бонус за Silver:\n⏩ 10 материалов\n` + break; + case 'gold': + business.materials += 20 + text += `⭐ Дополнительный бонус за Gold:\n⏩ 20 материалов\n` + break; + } + text += `⏩ ${mats} материалов в организацию\n` + business.materials += Number(mats) + business.save() + } + await user.save(); + await world.save(); + return ctx.reply(` + ⭐ Из ежечасного бонуса Вам выпало: +${text} + `) +} \ No newline at end of file diff --git a/commands/carcantainers/chooseContainer.js b/commands/carcantainers/chooseContainer.js new file mode 100644 index 0000000..2d2ea73 --- /dev/null +++ b/commands/carcantainers/chooseContainer.js @@ -0,0 +1,32 @@ +const { + rarecars, + simplecars, + UserModel, + PropertyModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let data = ctx.update.callback_query.data; + let user = await UserModel.findByPk(ctx.from.id) + let property = await PropertyModel.findByPk(ctx.from.id) + if(user.money < 500000) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Открытие контейнера стоит ₽500.000`, {show_alert: true}) + if(property.car.name) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас уже есть автомобиль\nПродайте текущий автомобиль: /sell car`, {show_alert: true}) + user.money -= 500000 + let userWin = null + switch(data){ + case `container_7`: + userWin = rarecars.random() + break; + default: + userWin = simplecars.random() + break; + } + property.car = userWin + user.save() + property.save() + ctx.deleteMessage() + return await ctx.sendPhoto(userWin.image, { caption: `В контейнере была: ${userWin.name} стоимостью ₽${spaces(userWin.price)}`}) +} \ No newline at end of file diff --git a/commands/carcantainers/containersMenu.js b/commands/carcantainers/containersMenu.js new file mode 100644 index 0000000..93d0444 --- /dev/null +++ b/commands/carcantainers/containersMenu.js @@ -0,0 +1,30 @@ +const { + UserModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let containers = [] + let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + let oneValue = [] + for(i = 0; i < 10; i++){ + oneValue = values.random() + values = values.filter(value => value != oneValue); + containers.push({name: `📦 Контейнер ${i+1}`, value: oneValue}) + } + let keyboardButtons = containers.map(container => { + return {text: container.name, callback_data: `container_${container.value}`} + }) + let rows = [] + while (keyboardButtons.length > 0) { + rows.push(keyboardButtons.splice(0, 2)) // разбиваем на подмассивы по 5 кнопок + } + console.log(containers) + await ctx.replyWithMarkdownV2('[Sueta Logistic International](https://telegra.ph/OOO-Sueta-Logistic-International-09-27)\nДоступные контейнеры в порту:', + { + reply_markup: { + inline_keyboard: rows + }, + disable_web_page_preview: true + }) +} \ No newline at end of file diff --git a/commands/casino/casinoMenu.js b/commands/casino/casinoMenu.js new file mode 100644 index 0000000..04dfcbf --- /dev/null +++ b/commands/casino/casinoMenu.js @@ -0,0 +1,13 @@ +const { + Markup +} = require('telegraf') + +module.exports = async (ctx) => { + return await ctx.reply('🏯 Добро пожаловать в казино "杜明"\n', Markup + .keyboard([ + ['🎰 Слоты'], + ['▶️ Меню'] + ]) + .resize() +) +} \ No newline at end of file diff --git a/commands/casino/slots.js b/commands/casino/slots.js new file mode 100644 index 0000000..27a45d8 --- /dev/null +++ b/commands/casino/slots.js @@ -0,0 +1,68 @@ +const { + slots, + UserModel, + WorldModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + getSlot, + giveExp, + setCooldown +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let data = ctx.update.callback_query.data; + let bet = 1000 + switch(data){ + case `slots1000`: + bet = 1000 + break; + case `slots5000`: + bet = 5000 + break; + case `slots25000`: + bet = 25000 + break; + case `slots50000`: + bet = 50000 + break; + case `slots100000`: + bet = 100000 + break; + } + let user = await UserModel.findByPk(ctx.from.id) + let timer = user.slottime + let cooldown = setCooldown(user, 10, timer) + if (user.slottime > cooldown.currentTime) return ctx.reply(`📛 Слоты будут доступны через пару секунд`); + if (user.money < bet) return ctx.reply(`Недостаточно средств.`) + user.slottime = cooldown.endTime + let world = await WorldModel.findByPk(1) + let result = await ctx.replyWithDice({emoji: `🎰`}) + let slot = slots[result.dice.value] + let win = getSlot(result) + console.log(user.username + `: Win: x` + win) + user.money -= bet + world.balance += bet + if(win > 4){ + user.world -= bet*win + user.money += bet*win + user.save() + world.save() + return setTimeout(() => { + ctx.reply(`➕ Вы выиграли ₽${spaces(bet*win)}`) + }, 1700); + } + if(win > 0 && win <= 4){ + await giveExp(user, win*2) + return setTimeout(() => { + ctx.reply(`➕ Вы выиграли ${win*2} опыта.`) + }, 1700); + } + if(win == 0){ + return setTimeout(() => { + world.save() + user.save() + ctx.reply(`➖ Вы проиграли ₽${spaces(bet)}.`) + }, 1700); + } +} \ No newline at end of file diff --git a/commands/casino/slotsMenu.js b/commands/casino/slotsMenu.js new file mode 100644 index 0000000..76e6081 --- /dev/null +++ b/commands/casino/slotsMenu.js @@ -0,0 +1,30 @@ +const { + Markup +} = require('telegraf') +const { + UserModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + ctx.args = ctx.update.message.text.split(' ') + await ctx.reply('Комбинации слотов:\n7️⃣7️⃣7️⃣ - x25\n🍋🍋🍋 - x20\n🍇🍇🍇 - x15\n🔤🔤🔤 - x10', Markup + .inlineKeyboard([ + [{ + text: `1000`, + callback_data: `slots1000` + }, { + text: `5000`, + callback_data: `slots5000` + }, { + text: `25000`, + callback_data: `slots25000` + }, { + text: `50000`, + callback_data: `slots50000` + }, { + text: `100000`, + callback_data: `slots100000` + }] + ])) +} \ No newline at end of file diff --git a/commands/erase.js b/commands/erase.js new file mode 100644 index 0000000..a3e75a7 --- /dev/null +++ b/commands/erase.js @@ -0,0 +1,67 @@ +const { + Telegraf, + Scenes, + session, + Stage, + Markup +} = require('telegraf') +const { + weaponshop, + slots, + rarecars, + simplecars, + houses, + cars, + phones, + weapons, + equipment, + UserModel, + WorldModel, + JobModel, + PropertyModel, + BusinessModel, + ReportModel, + BlockModel, + PromocodeModel, + mainChat, + adminList, + expToUp, + topSym +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + spacesWithMarkdown, + escape, + generatePromo, + generateVoucher, + getCurrentTime, + getSlot, + giveExp, + matPriceUpdate, + rand, + random, + setCooldown, + weaponShopUpdate, + stats +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { +// Получаем контекст canvas +const canvas = ctx.update.callback_query.message.photo[0].file_id; +const ctx = new Canvas(cardWidth, cardHeight); + +// Увеличиваем координаты верхнего слоя +topLayerX += 10; +topLayerY += 10; + +// Отправляем обновленную карточку +ctx.replyWithPhoto({ source: canvas.toBuffer() }, Markup.inlineKeyboard([ + Markup.callbackButton('Стереть', 'erase'), +]).extra()); + +// Проверяем, достиг ли верхний слой края карточки +if (topLayerX + cardWidth > cardWidth) { + // Отправляем сообщение с выигрышем + ctx.reply('Поздравляю, вы выиграли!'); +} +} \ No newline at end of file diff --git a/commands/getprofile.js b/commands/getprofile.js new file mode 100644 index 0000000..640e314 --- /dev/null +++ b/commands/getprofile.js @@ -0,0 +1,33 @@ +const { + UserModel, + PropertyModel, + expToUp +} = require('../config') +const { + spacesWithMarkdown, + escape +} = require('../utils') + +module.exports = async (ctx) => { + if(!ctx.message.reply_to_message) return await ctx.reply(`Только на пересланное сообщение.`) + let id = ctx.message.reply_to_message.from.id + let user = await UserModel.findByPk(id); + let property = await PropertyModel.findByPk(id); + return ctx.replyWithMarkdownV2(` + 👤${escape(user.username)} ${user.status == 'bronze' ? `\\[🔺\\]` : ""}${user.status == 'silver' ? `\\[🔹\\]` : ""}${user.status == 'gold' ? `\\[🔸\\]` : ""}${user.status == 'admin' ? "✅" : ""} + 🆔: ${ctx.from.id} + + 📶 Уровень: ${user.level} \\| ${user.exp} / ${expToUp[user.level]} + ⏩ Повышается за различные действия\\. + + 💰 Баланс + ₽${spacesWithMarkdown(user.money)} + + 🔵 Имущество + 🏠 Жилье: ${property.house == 0 ? "Бездомный" : property.house.name} + 🚗 Автомобиль: ${property.car == 0 ? "Пешком" : escape(property.car.name)} + 📱 Телефон: ${property.mobile == 0 ? "Нет" : property.mobile.name} + 🔫 Оружие: ${property.weapon == 0 ? "Безоружный" : property.weapon.name} + 🥼 Экипировка: ${property.equipment == 0 ? "Нет" : property.equipment.name} + `); +} \ No newline at end of file diff --git a/commands/index.js b/commands/index.js new file mode 100644 index 0000000..3bab193 --- /dev/null +++ b/commands/index.js @@ -0,0 +1,40 @@ +module.exports = { + profile: require('./profile'), + bonus: require('./bonus'), + menu: require('./menu'), + getprofile: require('./getprofile'), + pay: require('./pay'), + worldMenu: require('./world'), + referal: require('./invite'), + jobs: require('./jobs/jobs'), + chooseJob: require('./jobs/chooseJob'), + casinoMenu: require('./casino/casinoMenu'), + work: require('./jobs/work'), + top: require('./top'), + propertyMenu: require('./property/propertyMenu'), + propertyList: require('./property/propertyList'), + propertyBuy: require('./property/propertyBuy'), + hatkeisList: require('./property/hatkeisList'), + propertySell: require('./property/propertySell'), + organizationMenu: require('./organization/organizationMenu'), + workoff: require('./organization/workoff'), + leaveOrg: require('./organization/leaveOrg'), + leaveOrgAccept: require('./organization/leaveOrgAccept'), + payday: require('./organization/payday'), + orgMessage: require('./organization/orgMessage'), + materialsBuy: require('./organization/materialsBuy'), + percentSet: require('./organization/percentSet'), + organizationCreate: require('./organization/organizationCreate'), + invite: require('./organization/invite'), + inviteAction: require('./organization/inviteAction'), + report: require('./report'), + slotsMenu: require('./casino/slotsMenu'), + slotsRun: require('./casino/slots'), + promocodeActivate: require('./promocodeActivate'), + carContainers: require('./carcantainers/containersMenu'), + chooseContainer: require('./carcantainers/chooseContainer'), + reportAnswer: require('./admin/reportAnswer'), + fastblock: require('./admin/fastblock'), + createPromo: require('./admin/createPromo'), + genPromo: require('./admin/genPromo') +} \ No newline at end of file diff --git a/commands/invite.js b/commands/invite.js new file mode 100644 index 0000000..d3c88bf --- /dev/null +++ b/commands/invite.js @@ -0,0 +1,49 @@ +const { + weaponshop, + slots, + rarecars, + simplecars, + houses, + cars, + phones, + weapons, + equipment, + UserModel, + WorldModel, + JobModel, + PropertyModel, + BusinessModel, + ReportModel, + BlockModel, + PromocodeModel, + mainChat, + adminList, + expToUp, + topSym +} = require('../config') +const { + spaces, + spacesWithMarkdown, + escape, + generatePromo, + generateVoucher, + getCurrentTime, + getSlot, + giveExp, + matPriceUpdate, + rand, + random, + setCooldown, + weaponShopUpdate, + stats +} = require('../utils') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + return ctx.reply(` + ℹ️ Для приглашения друга по реферальной системе, отправьте ему ссылку-приглашение +Как только он перейдет по ней и начнет игру, Вы получите ₽25.000. + +Ваша ссылка: https://t.me/CampFireGameBot?start=${user.telegram_id} + `) +} \ No newline at end of file diff --git a/commands/jobs/chooseJob.js b/commands/jobs/chooseJob.js new file mode 100644 index 0000000..e38459c --- /dev/null +++ b/commands/jobs/chooseJob.js @@ -0,0 +1,96 @@ +const { + UserModel, + JobModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let data = ctx.update.callback_query.data; + let user = await UserModel.findByPk(ctx.from.id); + let job = null + switch(data){ + case `job_1`: + job = await JobModel.findByPk(1); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 1 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу дворником.\nВаш оклад: ₽${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_2`: + job = await JobModel.findByPk(2); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 2 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу промоутером. \nВаш оклад: ₽${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_3`: + job = await JobModel.findByPk(3); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 3 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу официантом. \nВаш оклад: ₽${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_4`: + job = await JobModel.findByPk(4); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 4 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу барменом. \nВаш оклад: ₽${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_5`: + job = await JobModel.findByPk(5); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 5 + user.save() + return await ctx.reply(`❕ Вы устроились на работу кассиром. \nВаш оклад: ₽${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`ℹ️ Вы уже устроены на другую работу`) + case `job_6`: + job = await JobModel.findByPk(6); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 6 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу в ПВЗ Дикие Ягоды. \nВаш оклад: ₽${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_7`: + job = await JobModel.findByPk(7); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 7 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу слесарем. \nВаш оклад: ₽${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_leave`: + if (user.job != 0) { + user.job = 0 + user.save() + return await ctx.reply(`ℹ️ Теперь вы безработный.`) + } + return await ctx.reply(`❕ Вы итак безработный.`) + } +} \ No newline at end of file diff --git a/commands/jobs/jobs.js b/commands/jobs/jobs.js new file mode 100644 index 0000000..259303b --- /dev/null +++ b/commands/jobs/jobs.js @@ -0,0 +1,36 @@ +const { + Markup +} = require('telegraf') + +module.exports = async (ctx) => { + return await ctx.reply('Список работы', Markup + .inlineKeyboard([ + [{ + text: `Дворник [1 уровень]`, + callback_data: 'job_1' + }, { + text: `Промоутер [1 уровень]`, + callback_data: 'job_2' + }], [{ + text: `Официант [2 уровень]`, + callback_data: 'job_3' + }, { + text: `Бармен [3 уровень]`, + callback_data: 'job_4' + }], [{ + text: `Кассир [4 уровень] `, + callback_data: 'job_5' + }, { + text: `ПВЗ Дикие Ягоды [4 уровень]`, + callback_data: 'job_6' + }], [{ + text: `Слесарь [5 уровень]`, + callback_data: 'job_7' + }], [{ + text: `💤 Уволиться`, + callback_data: 'job_leave' + }] + ]) + .resize() +) +} \ No newline at end of file diff --git a/commands/jobs/work.js b/commands/jobs/work.js new file mode 100644 index 0000000..a9b7d56 --- /dev/null +++ b/commands/jobs/work.js @@ -0,0 +1,191 @@ +const { + UserModel, + WorldModel, + JobModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + giveExp, + setCooldown +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + let job = await JobModel.findByPk(user.job); + let world = await WorldModel.findByPk(1) + let timer = user.jobtime + let cooldown = setCooldown(user, 3600, timer) + if (user.jobtime > cooldown.currentTime) return ctx.reply(`📛 Работать можно будет через ${cooldown.timeLeftInMinutes} минут(у/ы)`); + if (user.job == 0) { + return await ctx.reply(`📛 Вы безработный.`) + } + user.jobtime = Number(cooldown.endTime) + let jobExp = job.exp; + user.jobcheck++ + switch (user.job) { + case 1: + if (user.jobcheck >= 4) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену дворника. \n🧾 Расчетный лист: \n⏳ Отработано часов: 4/4 \n💸 Оклад: ₽${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ₽${payday}`) + } else { + user.save() + return ctx.reply(`👔 Вы подмели дворы. \n⏳ Отработано часов: ${user.jobcheck}/4`) + } + break; + case 2: + if (user.jobcheck >= 2) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену промоутера. \n🧾 Расчетный лист: \n⏳ Отработано часов: 2/2 \n💸 Оклад: ₽${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ₽${payday}`) + } else { + user.save() + return ctx.reply(`👔 Вы раздавали листовки целый час. \n⏳ Отработано часов: ${user.jobcheck}/2`) + } + break; + case 3: + if (user.jobcheck >= 4) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + let tips = [50, 100, 200, 500, 1000].random() + user.money += tips + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену официанта. \n🧾 Расчетный лист: \n⏳ Отработано часов: 4/4 \n💸 Оклад: ₽${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ₽${payday} \n💰 Получено чаевых: ₽${tips}`) + } else { + let tips = [50, 100, 200, 500, 1000].random() + user.money += tips + user.save() + return ctx.reply(`👔 Вы целый час бегали и отрабатывали заказы. \n🧾 Получено чаевых: ₽${tips} \n⏳ Отработано часов: ${user.jobcheck}/4`) + } + break; + case 4: + if (user.jobcheck >= 5) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + let tips = [50, 100, 200, 300, 500, 1000, 2000].random() + world.balance -= tips + user.money += tips + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену бармена. \n🧾 Расчетный лист: \n⏳ Отработано часов: 5/5 \n💸 Оклад: ₽${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ₽${payday} \n💰 Получено чаевых: ₽${tips}`) + } else { + let tips = [50, 100, 200, 300, 500, 1000, 2000].random() + world.balance -= tips + user.money += tips + user.save() + world.save() + return ctx.reply(`👔 Вы целый час стояли за стойкой и разливали пойло. \n🧾 Получено чаевых: ₽${tips} \n⏳ Отработано часов: ${user.jobcheck}/5`) + } + break; + case 5: + if (user.jobcheck >= 5) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену кассира. \n🧾 Расчетный лист: \n⏳ Отработано часов: 5/5 \n💸 Оклад: ₽${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ₽${payday}`) + } else { + user.save() + return ctx.reply(`👔 Вы целый час обслуживали покупателей и кричали: "Гаааляяя, отмена!". \n⏳ Отработано часов: ${user.jobcheck}/5`) + } + break; + case 6: + if (user.jobcheck >= 6) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + let stealed = [{ + name: "Помада", + price: 200 + }, { + name: "Бюстгалтер", + price: 1300 + }, { + name: "Прокладки", + price: 250 + }, { + name: "Перцовый балончик", + price: 600 + }, { + name: "Гитара", + price: 6500 + }, { + name: "Комбик", + price: 9000 + }, { + name: "Кроссовки", + price: 2000 + }, { + name: "Шампунь", + price: 180 + }, { + name: "Смартфон Texno", + price: 6999 + }, { + name: "TWS Гарнитура", + price: 2800 + }, { + name: "Геймпад GameStation 5", + price: 1400 + }, { + name: "Дилдо", + price: 600 + }, { + name: "Вагиноимитатор", + price: 600 + }].random() + world.balance -= payday + world.balance -= Number(stealed.price) + user.money += payday + user.money += Number(stealed.price) + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену в Диких Ягодах. \n🧾 Расчетный лист: \n⏳ Отработано часов: 6/6 \n💸 Оклад: ₽${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ₽${payday} \n💰 Вы украли и продали со склада: ${stealed.name} (₽${stealed.price})`) + } else { + user.save() + return ctx.reply(`👔 Вы целый час выдавали заказы в Диких Ягодах. \n⏳ Отработано часов: ${user.jobcheck}/6`) + } + break; + case 7: + if (user.jobcheck >= 6) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену слесарем. \n🧾 Расчетный лист: \n⏳ Отработано часов: 6/6 \n💸 Оклад: ₽${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ₽${payday}`) + } else { + user.save() + return ctx.reply(`👔 Вы целый час работали на заводе, вы молодец! \n⏳ Отработано часов: ${user.jobcheck}/6`) + } + break; + } +} \ No newline at end of file diff --git a/commands/menu.js b/commands/menu.js new file mode 100644 index 0000000..f5afcd3 --- /dev/null +++ b/commands/menu.js @@ -0,0 +1,15 @@ +const { + Markup +} = require('telegraf') + +module.exports = async (ctx) => { + return await ctx.reply('Main Menu', Markup + .keyboard([ + ['😎 Профиль'], + ['🗄️ Работать', '🌐 Организация', '🎁 Бонус', '🏯 Казино'], + ['📦 Контейнеры'], + ['📢 Вакансии', '🔵 Имущество', '📞 Пригласить'] + ]) + .resize() + ) +} diff --git a/commands/organization/invite.js b/commands/organization/invite.js new file mode 100644 index 0000000..d1aa160 --- /dev/null +++ b/commands/organization/invite.js @@ -0,0 +1,38 @@ +const { + Telegraf, + Markup +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1]) return ctx.reply(`/invite [Nick]`) + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`🚫 У вас нет организации в которую можно пригласить игрока.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if (business.users.length >= 5) return await ctx.reply(`📛 Достигнуто максимальное количество сотрудников в организации.`) + let invited = await UserModel.findOne({ + where: { + username: ctx.args[1] + } + }); + await bot.telegram.sendMessage(invited.telegram_id, '⤵️ Приглашение', Markup + .inlineKeyboard([ + [{ + text: `Принять`, + callback_data: `{"type": "business_invite_accept", "invitor": "${user.telegram_id}"}` + }, { + text: `Отклонить`, + callback_data: `{"type": "business_invite_refuse", "invitor": "${user.telegram_id}"}` + }] + ]).oneTime()) + return await ctx.reply(`Приглашение отправлено.`) +} \ No newline at end of file diff --git a/commands/organization/inviteAction.js b/commands/organization/inviteAction.js new file mode 100644 index 0000000..0b259f2 --- /dev/null +++ b/commands/organization/inviteAction.js @@ -0,0 +1,34 @@ +const sequelize = require('/workspace/degradin/Dev/Telegram/CampFire Play/db'); +const { Op } = require('sequelize'); +const { + UserModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let data = ctx.update.callback_query.data; + data = JSON.parse(data) + let user = await UserModel.findByPk(ctx.update.callback_query.from.id) + if (data.type == 'business_invite_accept') { + if(user.business.id == 0){ + let business = await BusinessModel.findOne({ + where: { + owner: data.invitor + } + }) + user.business = { + id: data.invitor, + checks: 0, + percent: 10 + } + business.users = sequelize.fn('array_append', sequelize.col('users'), ctx.update.callback_query.from.id); + business.save() + user.save() + await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `✔️ Приглашение принято.`, {show_alert: true}) + } + await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `ℹ️ Вы уже в организации.`, {show_alert: true}) + } + if (data.type == 'business_invite_refuse'){ + await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `❌ Приглашение отклонено.`, {show_alert: true}) + } +} \ No newline at end of file diff --git a/commands/organization/leaveOrg.js b/commands/organization/leaveOrg.js new file mode 100644 index 0000000..b3c5ee7 --- /dev/null +++ b/commands/organization/leaveOrg.js @@ -0,0 +1,41 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if(business === null){ + business = await BusinessModel.findOne({ + where: { + owner: user.business.id + } + }) + await ctx.reply(`Подтвердите в личных сообщениях.`) + return await bot.telegram.sendMessage(ctx.from.id, `🏭 Вы действительно хотите покинуть ${business.name}`, Markup.inlineKeyboard([ + [{ + text: `Да`, + callback_data: "user_leave_business" + }, { + text: `Нет`, + callback_data: "cancel" + }] + ]) + .oneTime() + .resize() + ) + } + if (business.owner == ctx.from.id){ + return await ctx.reply(`Вы не можете покинуть свою организацию.`) + } +} \ No newline at end of file diff --git a/commands/organization/leaveOrgAccept.js b/commands/organization/leaveOrgAccept.js new file mode 100644 index 0000000..cb50ca4 --- /dev/null +++ b/commands/organization/leaveOrgAccept.js @@ -0,0 +1,28 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let data = ctx.update.callback_query.data; + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) + let business = await BusinessModel.findOne({ + where: { + owner: user.business.id + } + }) + user.business = { + id: 0, + checks: 0, + percent: 0 + } + business.users = business.users.filter(value => value != ctx.from.id); + business.save() + user.save() + return await bot.telegram.sendMessage(ctx.from.id, `🏭 Вы покинули ${business.name}`) +} \ No newline at end of file diff --git a/commands/organization/materialsBuy.js b/commands/organization/materialsBuy.js new file mode 100644 index 0000000..f8c6907 --- /dev/null +++ b/commands/organization/materialsBuy.js @@ -0,0 +1,29 @@ +const { + UserModel, + WorldModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`🚫 Вы не владеете организацией.`) + let world = await WorldModel.findByPk(1) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if (business === null) return await ctx.reply(`🚫 У вас нет организации.`) + if (!ctx.args[1]) return ctx.reply(`🚫 Не указан аргумент.`) + if (!Number(ctx.args[1])) return ctx.reply(`ℹ️ Количество должно быть числом.`) + if (ctx.args[1] < 1) return ctx.reply(`ℹ️ Минимальное количество для покупки - 1`) + if (ctx.args[1]*world.matPrice > business.balance) return ctx.reply(`🚫 Недостаточно средств на балансе организации.`) + if (business.materials >= 700) return ctx.reply(`🚫 Склады полны.`) + if (business.materials + Number(ctx.args[1]) > 700) return ctx.reply(`🚫 Нет столько места на складах.\n Можно закупить еще ${700 - business.materials}`) + let count = Number(ctx.args[1]) + business.balance -= world.matPrice*count + business.materials += count + business.save() + return await ctx.reply(`➕ Закуплено ${ctx.args[1]} материалов для организации на сумму ₽${world.matPrice*count}`) +} \ No newline at end of file diff --git a/commands/organization/orgMessage.js b/commands/organization/orgMessage.js new file mode 100644 index 0000000..a0d1bfa --- /dev/null +++ b/commands/organization/orgMessage.js @@ -0,0 +1,24 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + if (!ctx.args[1]) return ctx.reply(`Не указан аргумент.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if (business === null) return await ctx.reply(`У вас нет организации.`) + for (i = 0; i < business.users.length; i++) { + user = await UserModel.findByPk(business.users[i]) + await bot.telegram.sendMessage(user.telegram_id, `Директор организации сообщает:\n ${ctx.payload}`) + } + console.log(`Директор организации сообщает:\n ${ctx.payload}`) + return await ctx.reply(`Сообщение отправлено.`) +} \ No newline at end of file diff --git a/commands/organization/organizationCreate.js b/commands/organization/organizationCreate.js new file mode 100644 index 0000000..c3c863e --- /dev/null +++ b/commands/organization/organizationCreate.js @@ -0,0 +1,45 @@ +const { + UserModel, + WorldModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id != 0){ + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + } + let business = null + let world = await WorldModel.findByPk(1) + ctx.args = ctx.update.message.text.split(' ') + if (business != null) return await ctx.reply(`У вас уже есть организация.`) + if (!ctx.args[1]) return ctx.reply(`/business [Название организации]`) + if (user.money < 100000) return await ctx.reply(`Регистрация организации стоит ₽100.000`) + if (user.level < 5) return await ctx.reply(`Регистрация организации доступна с 5 уровня.`) + user.money -= 100000 + world.balance += 100000 + let text = `` + for (i = 1; i < ctx.args.length; i++) { + text += `${ctx.args[i]} ` + } + if (business === null) { + BusinessModel.create({ + name: text, + owner: user.telegram_id, + balance: 50000, + users: [user.telegram_id] + }) + user.business = { + id: user.telegram_id, + checks: 0, + percent: 100 + } + } else {} + user.save() + world.save() + return await ctx.reply(`Организация "${text}" успешно создана!\n Регистрация организации в реестре: ₽50.000 \n Капитал: ₽50.000`) +} \ No newline at end of file diff --git a/commands/organization/organizationMenu.js b/commands/organization/organizationMenu.js new file mode 100644 index 0000000..bddf056 --- /dev/null +++ b/commands/organization/organizationMenu.js @@ -0,0 +1,57 @@ +const { + Markup +} = require('telegraf') +const { + UserModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + escape +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if(business === null){ + business = await BusinessModel.findOne({ + where: { + owner: user.business.id + } + }) + return await ctx.replyWithMarkdownV2(`🏭 Организация\n_${business.name}_\n💹 Баланс: ₽${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n\nВаши отработки: ${user.business.checks}`, Markup.inlineKeyboard([ + [{ + text: `📶 Отработка`, + callback_data: "workoff" + }, { + text: `⬅️ Покинуть`, + callback_data: "покинуть" + }] + ]) + .oneTime() + .resize()) + } + if (business.owner == ctx.from.id){ + let text = `` + for (n = 0; n < business.users.length; n++) { // Процент выплаты участникам + users = await UserModel.findByPk(business.users[n]) + text += `${users.username} - ${users.business.checks} [${users.business.percent}%]\n` + } + return await ctx.replyWithMarkdownV2(`🏭 Ваша организация\n_${business.name}_\n💹 Баланс: ₽${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n🔨 Отработок: ${business.checks}\n${escape(text)}\n\nВаши отработки: ${user.business.checks}`, Markup.inlineKeyboard([ + [{ + text: `📶 Отработка`, + callback_data: "workoff" + }, { + text: `💸 Payday`, + callback_data: "payday" + }] + ]) + .oneTime() + .resize()) + } +} \ No newline at end of file diff --git a/commands/organization/payday.js b/commands/organization/payday.js new file mode 100644 index 0000000..73a1a59 --- /dev/null +++ b/commands/organization/payday.js @@ -0,0 +1,70 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + WorldModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + giveExp, + rand +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let user = null + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + let world = await WorldModel.findByPk(1) + if (business === null) return await ctx.reply(`У вас нет организации.`) + if (business.checks < 12) return await ctx.reply(`Недостаточно отработок для формирования выплаты.`) + let percentSum = 0 + let text = `` + let percentErrorText = `` + let profit = 0 + let piece = 0 + let moneyList = rand(1000, 3000) + moneyList = moneyList*business.users.length + for (i = 0; i < business.users.length; i++) { // Summary percent + user = await UserModel.findByPk(business.users[i]) + percentSum += Number(user.business.percent) + percentErrorText += `ℹ️ ${user.username} ${user.business.percent}% [/percent ${user.username} [проценты]]\n` + } + if (percentSum > 100) return await ctx.reply(`⚠️ Общий процент всех сотрудников превышает 100%\n ➕ Остаток процентов перенесется в баланс организации.\n\n${percentErrorText}\n`) + for (x = 0; x < business.users.length; x++) { // Общая внесенная сумма всеми участниками + user = await UserModel.findByPk(business.users[x]) + profit += user.business.checks * moneyList * user.level + text += `ℹ️ ${user.username} отработал ${user.business.checks} раз.\n` + user.business = { + id: user.business.id, + checks: 0, + percent: user.business.percent + } + user.save() + } + text += ` 💹 Наработка за текущий период: ${profit}\n` + let profitCheck = profit + for (n = 0; n < business.users.length; n++) { // Процент выплаты участникам + user = await UserModel.findByPk(business.users[n]) + piece = Math.round(profit / 100 * user.business.percent) + profitCheck -= piece + user.money += piece + text += `➕ ${user.username} получает ₽${piece}\n` + await bot.telegram.sendMessage(user.telegram_id, `ℹ️ Директор организации сформировал выплаты.\n➕ На ваш баланс поступило: ₽${spaces(piece)}`) + giveExp(user, business.checks) + user.save() + } + if (profitCheck > 0) { + business.balance += profitCheck + text += `➕ На баланс бизнеса поступило ₽${profitCheck}` + } + business.checks = 0 + business.save() + console.log(`Payday: ${business.name}\n${text}`) + return await ctx.reply(text) +} \ No newline at end of file diff --git a/commands/organization/percentSet.js b/commands/organization/percentSet.js new file mode 100644 index 0000000..6ffdae3 --- /dev/null +++ b/commands/organization/percentSet.js @@ -0,0 +1,34 @@ +const { + UserModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`Вы не владеете организацией.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if (business === null) return await ctx.reply(`У вас нет организации.`) + if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`Не указан аргумент.`) + if (!Number(ctx.args[2])) return ctx.reply(`Процент должен быть числом от 1 до 100.`) + if (ctx.args[2] < 1 || ctx.args[2] > 100) return ctx.reply(`Минимальный процент 1 | Максимальный процент 100.`) + ctx.args[1] = ctx.args[1] + console.log(ctx.args) + let change = await UserModel.findOne({ + where: { + username: ctx.args[1] + } + }) + if (change === null) return await ctx.reply(`Нет такого игрока.`) + change.business = { + id: change.business.id, + checks: change.business.checks, + percent: ctx.args[2] + } + change.save() + return await ctx.reply(`Участнику ${change.username} установлен процент ${ctx.args[2]}`) +} \ No newline at end of file diff --git a/commands/organization/workoff.js b/commands/organization/workoff.js new file mode 100644 index 0000000..e4064ec --- /dev/null +++ b/commands/organization/workoff.js @@ -0,0 +1,71 @@ +const { + UserModel, + BusinessModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + escape, + setCooldown +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let business = await BusinessModel.findOne({ + where: { + owner: user.business.id.toString() + } + }) + if (user.business == null) return await ctx.reply(`Вы не работаете в организации.`) + let timer = user.worktime + let cooldown = setCooldown(user, 3600, timer) + if (user.worktime > cooldown.currentTime) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `📛 Работа в организации будет доступна через ${cooldown.timeLeftInMinutes} минут(у/ы)`, {show_alert: true}); + if (business.materials < 10) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `📛 В организации недостаточно материалов для отработки.`); + user.worktime = cooldown.endTime + user.business = { + id: user.business.id, + checks: user.business.checks + 1, + percent: user.business.percent + } + business.materials -= 10 + business.checks += 1 + await user.save() + await business.save() + if (business.owner == ctx.from.id){ + let text = `` + for (n = 0; n < business.users.length; n++) { // Процент выплаты участникам + users = await UserModel.findByPk(business.users[n]) + text += `${users.username} - ${users.business.checks} [${users.business.percent}%]\n` + } + return await ctx.editMessageText(`🏭 Ваша организация\n_${business.name}_\n💹 Баланс: ₽${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials} \n👥 Рабочих: ${business.users.length}\n🔨 Отработок: ${business.checks}\n${escape(text)}\n\nВаши отработки: ${user.business.checks}`, + { + reply_markup: { + inline_keyboard: [ + [{ + text: `📶 Отработка`, + callback_data: "workoff" + }, { + text: `💸 Payday`, + callback_data: "payday" + }] + ]}, + parse_mode: `MarkdownV2` + } + ) + }else{ + return await ctx.editMessageText(`🏭 Организация\n_${business.name}_\n💹 Баланс: ₽${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n\nВаши отработки: ${user.business.checks}`, + { + reply_markup: { + inline_keyboard: [ + [{ + text: `📶 Отработка`, + callback_data: "workoff" + }, { + text: `⬅️ Покинуть`, + callback_data: "покинуть" + }] + ]}, + parse_mode: `MarkdownV2` + } + ) + } +} \ No newline at end of file diff --git a/commands/pay.js b/commands/pay.js new file mode 100644 index 0000000..13c2016 --- /dev/null +++ b/commands/pay.js @@ -0,0 +1,35 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + WorldModel +} = require('../config') + +module.exports = async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`/pay [Никнейм] [Сумма]`) + if (!Number(ctx.args[2])) return ctx.reply(`❕ Сумма должна быть числовая.`) + let sender = await UserModel.findByPk(ctx.from.id); + let receiver = await UserModel.findOne({ + where: { + username: ctx.args[1] + } + }); + let world = await WorldModel.findByPk(1) + let fee = Number(Math.trunc(ctx.args[2] / 100 * world.transactionfee)) + if (ctx.args[2] == 0 || ctx.args[2] < 100) return ctx.reply(`❕ Минимальная сумма перевода ₽100.`) + if (sender.money < ctx.args[2]) return ctx.reply(`❕ Недостаточно средств!`) + if (sender.money < Number(ctx.args[2]) + fee) return ctx.reply(`❕ Недостаточно средств для перевода с комиссией!`) + sender.money -= Number(ctx.args[2]) + sender.money -= Number(fee) + world.balance += Number(fee) + await sender.save(); + await world.save(); + receiver.money += Number(ctx.args[2]) + await receiver.save(); + let pmToReceiver = `🔽 Входящий перевод.\n\n🔼 Отправитель: ${sender.username}\n🆔 Отправителя: ${sender.telegram_id}\n🔢 Сумма: ₽${ctx.args[2]}\n🆕 Ваш баланс: ₽${receiver.money}` + bot.telegram.sendMessage(receiver.telegram_id, pmToReceiver) + return ctx.reply(`🔼 Исходящий перевод.\n\n🔽 Получатель: ${receiver.username}\n🆔 Получателя: ${receiver.telegram_id}\n🔢 Сумма: ₽${ctx.args[2]}\nℹ️ Комиссия: ₽${fee}\n🆕 Ваш баланс: ₽${sender.money}`) +} \ No newline at end of file diff --git a/commands/profile.js b/commands/profile.js new file mode 100644 index 0000000..dac1476 --- /dev/null +++ b/commands/profile.js @@ -0,0 +1,32 @@ +const { + UserModel, + PropertyModel, + expToUp +} = require('../config') +const { + spacesWithMarkdown, + escape +} = require('../utils') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + let property = await PropertyModel.findByPk(ctx.from.id); + if (!user) return ctx.reply(`Ошибка #1`); + return ctx.replyWithMarkdownV2(` + 👤${escape(user.username)} ${user.status == 'bronze' ? `\\[🔺\\]` : ""}${user.status == 'silver' ? `\\[🔹\\]` : ""}${user.status == 'gold' ? `\\[🔸\\]` : ""}${user.status == 'admin' ? "✅" : ""} + 🆔: ${ctx.from.id} + + 📶 Уровень: ${user.level} \\| ${user.exp} / ${expToUp[user.level]} + ⏩ Повышается за различные действия\\. + + 💰 Баланс + ₽${spacesWithMarkdown(user.money)} + + 🔵 Имущество + 🏠 Жилье: ${property.house == 0 ? "Бездомный" : property.house.name} + 🚗 Автомобиль: ${property.car == 0 ? "Пешком" : escape(property.car.name)} + 📱 Телефон: ${property.mobile == 0 ? "Нет" : property.mobile.name} + 🔫 Оружие: ${property.weapon == 0 ? "Безоружный" : property.weapon.name} + 🥼 Экипировка: ${property.equipment == 0 ? "Нет" : property.equipment.name} + `); +} \ No newline at end of file diff --git a/commands/promocodeActivate.js b/commands/promocodeActivate.js new file mode 100644 index 0000000..97c8c23 --- /dev/null +++ b/commands/promocodeActivate.js @@ -0,0 +1,34 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + PromocodeModel, + adminList +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces +} = require('../utils') +const sequelize = require('../db'); + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1]) return ctx.reply(`/promocode [Code]`) + let promocode = await PromocodeModel.findOne({ + where: { + code: ctx.args[1] + } + }) + if(promocode === null) return await ctx.reply(`➖ Нет такого кода.`) + if(promocode.users.length-1 >= promocode.activations && promocode.users != null) return await ctx.reply(`⚠️ Промокод уже активировали максимальное количество раз.`) + if(promocode.users.includes(ctx.from.id.toString())) return await ctx.reply(`⚠️ Вы уже активировали этот промокод.`) + console.log(promocode.users) + promocode.users = sequelize.fn('array_append', sequelize.col('users'), ctx.from.id.toString()); + user.money += promocode.money + user.save() + promocode.save() + await bot.telegram.sendMessage(adminList[0], `${user.username} активировал промокод на ₽${spaces(promocode.money)}`) + return await ctx.reply(`✅ Вы активировали промокод на ₽${spaces(promocode.money)}`) +} \ No newline at end of file diff --git a/commands/property/hatkeisList.js b/commands/property/hatkeisList.js new file mode 100644 index 0000000..b536b71 --- /dev/null +++ b/commands/property/hatkeisList.js @@ -0,0 +1,18 @@ +const { + weaponshop +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + escape, + weaponShopUpdate +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let text = `[Hatkeis Gunsmith](https://telegra.ph/Hatkeis-Gunsmith-09-27)` + let shop = `\n Вы подходите к зданию с вывеской "Ништяки Хаткейса".\n Вот ассортимент на сегодня\n` + for (i = 0; i < 10; i++) { + shop += `${i}. ${weaponshop[i].name} (₽${spaces(weaponshop[i].price)})\n` + } + weaponShopUpdate() + return await ctx.replyWithMarkdownV2(text + escape(shop), {disable_web_page_preview: true}) +} \ No newline at end of file diff --git a/commands/property/propertyBuy.js b/commands/property/propertyBuy.js new file mode 100644 index 0000000..24d307a --- /dev/null +++ b/commands/property/propertyBuy.js @@ -0,0 +1,102 @@ +const { + weaponshop, + slots, + rarecars, + simplecars, + houses, + cars, + phones, + weapons, + equipment, + UserModel, + WorldModel, + JobModel, + PropertyModel, + BusinessModel, + ReportModel, + BlockModel, + PromocodeModel, + mainChat, + adminList, + expToUp, + topSym +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + spacesWithMarkdown, + escape, + generatePromo, + generateVoucher, + getCurrentTime, + getSlot, + giveExp, + matPriceUpdate, + rand, + random, + setCooldown, + weaponShopUpdate, + stats +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + let data = ctx.update.callback_query.data; + data = JSON.parse(data) + let user = await UserModel.findByPk(ctx.from.id) + let property = await PropertyModel.findByPk(ctx.from.id); + let world = await WorldModel.findByPk(1) + if (data.type == "house") { + if (user.money < houses[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) + if (property.house.name) return await ctx.reply(`У вас уже есть дом.`) + user.money -= houses[data.value].price + world.balance += houses[data.value].price + property.house = houses[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${houses[data.value].name}`) + } + if (data.type == "car") { + if (user.money < cars[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) + if (property.car.name) return await ctx.reply(`У вас уже есть автомобиль.`) + if (!property.house.name) return await ctx.reply(`Для покупки автомобиля, у Вас должен быть дом.`) + user.money -= cars[data.value].price + world.balance += cars[data.value].price + property.car = cars[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${cars[data.value].name}`) + } + if (data.type == "phone") { + if (user.money < phones[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) + if (property.mobile.name) return await ctx.reply(`У вас уже есть телефон.`) + user.money -= phones[data.value].price + world.balance += phones[data.value].price + property.mobile = phones[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${phones[data.value].name}`) + } + if (data.type == "equipment") { + if (user.money < weaponshop[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) + if (data.type == weaponshop[data.value].type) { + if (property.equipment.name) return await ctx.reply(`У вас уже есть экипировка.`) + user.money -= weaponshop[data.value].price + world.balance += weaponshop[data.value].price + property.equipment = weaponshop[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${weaponshop[data.value].name}`) + } + if (property.weapon.name) return await ctx.reply(`У вас уже есть оружие.`) + user.money -= weaponshop[data.value].price + world.balance += weaponshop[data.value].price + property.weapon = weaponshop[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${weaponshop[data.value].name}`) + } +} \ No newline at end of file diff --git a/commands/property/propertyList.js b/commands/property/propertyList.js new file mode 100644 index 0000000..65fd12a --- /dev/null +++ b/commands/property/propertyList.js @@ -0,0 +1,42 @@ +const { + Markup +} = require('telegraf') +const { + houses, + cars, + phones +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let data = ctx.update.callback_query.data; + let prodArray = [] + let text = `Доступно к покупке:\n` + switch(data){ + case `shop_house`: + for (i in houses) { + prodArray.push({text: i, callback_data: `{"action": "buy", "type": "house", "value": "${i}"}`}) + text += i + `. ${houses[i].name} (₽${houses[i].price})\n` + } + break; + case `shop_phone`: + for (i in phones) { + prodArray.push({text: i, callback_data: `{"action": "buy", "type": "phone", "value": "${i}"}`}) + text += i + `. ${phones[i].name} (₽${phones[i].price})\n` + } + break; + case `shop_car`: + for (i in cars) { + prodArray.push({text: i, callback_data: `{"action": "buy", "type": "car", "value": "${i}"}`}) + text += i + `. ${cars[i].name} (₽${cars[i].price})\n` + } + break; + } + prodArray.push({text: `Назад`, callback_data: `shopmenu`}) + let rows = [] + while (prodArray.length > 0) { + rows.push(prodArray.splice(0, 5)) // разбиваем на подмассивы по 5 кнопок + } + return await ctx.editMessageText(text, Markup + .inlineKeyboard(rows) + .resize()) +} \ No newline at end of file diff --git a/commands/property/propertyMenu.js b/commands/property/propertyMenu.js new file mode 100644 index 0000000..e123a32 --- /dev/null +++ b/commands/property/propertyMenu.js @@ -0,0 +1,19 @@ +const { + Markup +} = require('telegraf') +const { + UserModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + return await ctx.reply(`Выберите тип`, Markup + .inlineKeyboard([ + [ + {text: 'Жилье', callback_data: `shop_house`}, + {text: 'Телефоны', callback_data: `shop_phone`}, + {text: 'Автосалон', callback_data: `shop_car`} + ] + ]) + .resize()) +} \ No newline at end of file diff --git a/commands/property/propertySell.js b/commands/property/propertySell.js new file mode 100644 index 0000000..a76c40e --- /dev/null +++ b/commands/property/propertySell.js @@ -0,0 +1,102 @@ +const { + weaponshop, + slots, + rarecars, + simplecars, + houses, + cars, + phones, + weapons, + equipment, + UserModel, + WorldModel, + JobModel, + PropertyModel, + BusinessModel, + ReportModel, + BlockModel, + PromocodeModel, + mainChat, + adminList, + expToUp, + topSym +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + spacesWithMarkdown, + escape, + generatePromo, + generateVoucher, + getCurrentTime, + getSlot, + giveExp, + matPriceUpdate, + rand, + random, + setCooldown, + weaponShopUpdate, + stats +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') + +module.exports = async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + let user = await UserModel.findByPk(ctx.from.id) + let property = await PropertyModel.findByPk(ctx.from.id); + let world = await WorldModel.findByPk(1) + if (!ctx.args[1]) return ctx.reply(`Не указан аргумент.`) + if (ctx.args[1] == "house") { + if (!property.house.name) return await ctx.reply(`У вас нет дома.`) + let name = property.house.name + user.money += Math.round(property.house.price/2) + world.balance -= Math.round(property.house.price/2) + property.house = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } + if (ctx.args[1] == "car") { + if (!property.car.name) return await ctx.reply(`У вас нет автомобиля.`) + let name = property.car.name + user.money += Math.round(property.car.price/2) + world.balance -= Math.round(property.car.price/2) + property.car = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } + if (ctx.args[1] == "phone") { + if (!property.mobile.name) return await ctx.reply(`У вас нет телефона.`) + let name = property.mobile.name + user.money += Math.round(property.mobile.price/2) + world.balance -= Math.round(property.mobile.price/2) + property.mobile = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } + if (ctx.args[1] == "equipment") { + if (!property.equipment.name) return await ctx.reply(`У вас нет экипировки.`) + let name = property.equipment.name + user.money += Math.round(property.equipment.price/2) + world.balance -= Math.round(property.equipment.price/2) + property.equipment = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } + if (ctx.args[1] == "weapon") { + if (!property.weapon.name) return await ctx.reply(`У вас нет оружия.`) + let name = property.weapon.name + user.money += Math.round(property.weapon.price/2) + world.balance -= Math.round(property.weapon.price/2) + property.weapon = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } +} \ No newline at end of file diff --git a/commands/report.js b/commands/report.js new file mode 100644 index 0000000..9a66601 --- /dev/null +++ b/commands/report.js @@ -0,0 +1,31 @@ +const { + Telegraf, + Markup +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + UserModel, + ReportModel, + adminList +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const shortid = require('shortid'); + +module.exports = async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1]) return ctx.reply(`/report [Текст обращения]`) + let uID = shortid.generate() + await ReportModel.create({ + uid: uID, + author: user.telegram_id, + text: ctx.payload, + status: 1 + }) + let report = await ReportModel.findOne({ + where: { + uid: uID + } + }) + await bot.telegram.sendMessage(adminList[0], `Обращение от пользователя ${user.username}\nТекст обращения:\n${ctx.payload}\n\nДля ответа /answer ${report.id} [Ответ]`) + return await ctx.reply(`Обращение #${report.id}[${report.uid}] создано.`) +} \ No newline at end of file diff --git a/commands/scratch.js b/commands/scratch.js new file mode 100644 index 0000000..f9e1f6f --- /dev/null +++ b/commands/scratch.js @@ -0,0 +1,7 @@ +const { createCanvas, loadImage } = require('canvas'); +const fs = require('fs'); + +module.exports = async (ctx) => { + + +} \ No newline at end of file diff --git a/commands/top.js b/commands/top.js new file mode 100644 index 0000000..952ae57 --- /dev/null +++ b/commands/top.js @@ -0,0 +1,30 @@ +const { + UserModel, + topSym +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') +const sequelize = require('../db'); +const { Op } = require('sequelize'); + +module.exports = async (ctx) => { + let topPlayer = await UserModel.findAll({ + attributes: ['name', [sequelize.fn('sum', sequelize.col('money')), 'money'], 'status'], + group: ['name', 'status'], + where: { + telegram_id: { + [Op.ne]: 275416286 + } + }, + order: [ + [sequelize.literal('money'), 'DESC'] + ], + limit: 10 + }) + let text = `🏆 Топ 10 игроков по балансу.\n\n` + for(i=0; i { + let world = await WorldModel.findByPk(1) + return ctx.reply(`🔰 Баланс мира: ₽${spaces(world.balance)}\nℹ️ Стоимость материалов: ₽${spaces(world.matPrice)} + `) +} \ No newline at end of file diff --git a/config/imports.js b/config/imports.js new file mode 100644 index 0000000..734e28a --- /dev/null +++ b/config/imports.js @@ -0,0 +1,48 @@ + +const testScene = require("../scenes/test"); +const weaponshop = require('../json/weaponshop.json') +const slots = require('../json/slots.json') +const rarecars = require('../json/rarecars.json') +const simplecars = require('../json/simplecars.json') +const houses = require('../presets/houses.json') +const cars = require('../presets/cars.json') +const phones = require('../presets/mobiles.json') +const weapons = require('../presets/weapons.json') +const equipment = require('../presets/equipment.json') +const UserModel = require('../models/user.model'); +const WorldModel = require('../models/world.model'); +const JobModel = require('../models/job.model'); +const PropertyModel = require('../models/property.model'); +const BusinessModel = require('../models/business.model'); +const ReportModel = require('../models/report.model'); +const BlockModel = require('../models/block.model'); +const PromocodeModel = require('../models/promocode.model'); +const mainChat = -1001895132127 +const adminList = [275416286] +const expToUp = [0, 10, 20, 40, 60, 100, 250, 370, 450, 575, 666, 777, 860, 999, 1000, 1177, 1234, 1350, 1488, 1515, 1610] +const topSym = ['🥇', '🥈', '🥉', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'] + +module.exports = [ + testScene, + weaponshop, + slots, + rarecars, + simplecars, + houses, + cars, + phones, + weapons, + equipment, + UserModel, + WorldModel, + JobModel, + PropertyModel, + BusinessModel, + ReportModel, + BlockModel, + PromocodeModel, + mainChat, + adminList, + expToUp, + topSym +] \ No newline at end of file diff --git a/config/index.js b/config/index.js new file mode 100644 index 0000000..3e8a5e5 --- /dev/null +++ b/config/index.js @@ -0,0 +1,26 @@ +module.exports = { + testScene : require("../scenes/test"), + weaponshop : require('../json/weaponshop.json'), + slots : require('../json/slots.json'), + rarecars : require('../json/rarecars.json'), + simplecars : require('../json/simplecars.json'), + houses : require('../presets/houses.json'), + cars : require('../presets/cars.json'), + phones : require('../presets/mobiles.json'), + weapons : require('../presets/weapons.json'), + equipment : require('../presets/equipment.json'), + UserModel : require('../models/user.model'), + WorldModel : require('../models/world.model'), + JobModel : require('../models/job.model'), + PropertyModel : require('../models/property.model'), + BusinessModel : require('../models/business.model'), + ReportModel : require('../models/report.model'), + BlockModel : require('../models/block.model'), + PromocodeModel : require('../models/promocode.model'), + mainChat : -1001895132127, + adminList : [275416286], + expToUp : [0, 10, 20, 40, 60, 100, 250, 370, 450, 575, 666, 777, 860, 999, 1000, 1177, 1234, 1350, 1488, 1515, 1610], + topSym : ['🥇', '🥈', '🥉', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'], + promoTopicId: 1807, + gameTopicId: 1808 +} \ No newline at end of file diff --git a/ctxconfig.json b/ctxconfig.json new file mode 100644 index 0000000..4f51ceb --- /dev/null +++ b/ctxconfig.json @@ -0,0 +1,14 @@ +{ + "mainAdminId": 275416286, + "logChatId": -1001948614034, + "stickerLinkPrefix": "t.me/addstickers/", + "emojiLinkPrefix": "t.me/addemoji/", + "charTitleMax": 35, + "premiumCharTitleMax": 64, + "messaging": { + "limit": { + "max": 20, + "duration": 1500 + } + } + } \ No newline at end of file diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 0000000..44ac232 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,15 @@ +module.exports = { + apps: [{ + name: 'CampFireGame', + script: './index.js', + max_memory_restart: '4000M', + watch: true, + cron_restart: '0 */6 * * *', // restart every 6 hours + env: { + NODE_ENV: 'development' + }, + env_production: { + NODE_ENV: 'production' + } + }] + } \ No newline at end of file diff --git a/handlers/catch.js b/handlers/catch.js new file mode 100644 index 0000000..7004ead --- /dev/null +++ b/handlers/catch.js @@ -0,0 +1,54 @@ +const util = require('util') +const exec = util.promisify(require('child_process').exec) +const errorStackParser = require('error-stack-parser') +const { escapeHTML } = require('../utils') + +async function errorLog (error, ctx) { + const errorInfo = errorStackParser.parse(error) + + let gitBlame + + for (const ei of errorInfo) { + if (!gitBlame) gitBlame = await exec(`git blame -L ${ei.lineNumber},${ei.lineNumber} -- ${ei.fileName}`).catch(() => {}) + } + + let errorText = `error for ${ctx.updateType}:` + if (ctx.match) errorText += `\n${ctx.match[0]}` + if (ctx.from && ctx.from.id) errorText += `\n\nuser: ${escapeHTML(ctx.from.first_name)} #user_${ctx.from.id}` + if (ctx?.session?.chainActions && ctx?.session.chainActions.length > 0) errorText += '\n\n🔗 ' + ctx?.session.chainActions.map(v => `${v}`).join(' ➜ ') + + if (gitBlame && !gitBlame.stderr) { + const parsedBlame = gitBlame.stdout.match(/^(?[0-9a-f]+)\s+\((?.+)(?\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [+-]\d{4}\s+)(?\d+)\) ?(?.*)$/m) + + errorText += `\n\n${parsedBlame.groups.USER.trim()}` + errorText += `\ncommit: ${parsedBlame.groups.SHA}` + errorText += `\n\n${parsedBlame.groups.code}` + } + + errorText += `\n\n\n${escapeHTML(error.stack)}` + + if (error.description && error.description.includes('timeout')) return + + if (!ctx.config) return console.error(errorText) + + await ctx.telegram.sendMessage(ctx.config.logChatId, errorText, { + parse_mode: 'HTML' + }).catch((error) => { + console.error('send log error:', error) + }) + + if (ctx?.chat?.type === 'private') { + await ctx.replyWithHTML((` + Произошла неизвестная ошибка. + Вероятно, о ней уже известно администратору, но вы всё равно можете дополнительно сообщить последовательность, которая привела к ошибке => @Degradin. + Пожалуйста, сразу подробно опишите проблему в одном сообщении, можно приложить скрин.`)).catch(() => {}) + } +} + +module.exports = async (error, ctx) => { + console.error(error) + + errorLog(error, ctx).catch(e => { + console.error('errorLog error:', e) + }) +} \ No newline at end of file diff --git a/handlers/index.js b/handlers/index.js new file mode 100644 index 0000000..8bc5213 --- /dev/null +++ b/handlers/index.js @@ -0,0 +1,3 @@ +module.exports = { + handleError: require('./catch') +} \ No newline at end of file diff --git a/index backup.js b/index backup.js new file mode 100644 index 0000000..6748358 --- /dev/null +++ b/index backup.js @@ -0,0 +1,1763 @@ +require('dotenv').config() +const { + Telegraf, + Markup +} = require('telegraf') +const shortid = require('shortid'); +const voucher_codes = require('voucher-code-generator'); +const { createCanvas, loadImage } = require('canvas'); +const fs = require('fs') +const bot = new Telegraf(process.env.BOT_TOKEN) +const weaponshop = require('./json/weaponshop.json') +const slots = require('./json/slots.json') +const rarecars = require('./json/rarecars.json') +const simplecars = require('./json/simplecars.json') +const houses = require('./presets/houses.json') +const cars = require('./presets/cars.json') +const phones = require('./presets/mobiles.json') +const weapons = require('./presets/weapons.json') +const equipment = require('./presets/equipment.json') +const sequelize = require('./db'); +const { Op } = require('sequelize'); +const UserModel = require('./models/user.model'); +const WorldModel = require('./models/world.model'); +const JobModel = require('./models/job.model'); +const PropertyModel = require('./models/property.model'); +const BusinessModel = require('./models/business.model'); +const ReportModel = require('./models/report.model'); +const BlockModel = require('./models/block.model'); +const PromocodeModel = require('./models/promocode.model'); +const mainChat = -1001895132127 +const adminList = [275416286] +const expToUp = [0, 10, 20, 40, 60, 100, 250, 370, 450, 575, 666, 777, 860, 999, 1000, 1177, 1234, 1350, 1488, 1515, 1610] +const topSym = ['🥇', '🥈', '🥉', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'] + +const start = async () => { + try { + await sequelize.authenticate() + await sequelize.sync() + } catch (e) { + console.log('Подключение к бд сломалось', e) + } +} + +bot.telegram.setMyCommands([{ + command: "pay", + description: "Перевести указанному пользователю сумму." + }, + { + command: "buy", + description: "Приобрести указанное имущество." + }, + { + command: "business", + description: "Создать организацию." + }, + { + command: "invite", + description: "Пригласить пользователя в организацию." + }, + { + command: "percent", + description: "Установить пользователю процент заработка." + }, + { + command: "report", + description: "Создать жалобу/обращение/идею." + } +]) + +bot.use(async (ctx, next) => { + let id = ctx.from.id + let username = ctx.from.username + if(username == null) username = ctx.from.id + try { + console.log(getCurrentTime() + `: ` + username + `: ` + ctx.update.message.text) + } catch (e) { + console.log(getCurrentTime() + `: ${username}: ${ctx.update.callback_query.data}`) + } + let user = await UserModel.findByPk(id); + let block = await BlockModel.findByPk(id); + let property = await PropertyModel.findByPk(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 + }) + } else {} + //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() + return next().then(() => { + const ms = Date.now() - start + console.log('response time %sms', ms) + }) +}) + +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) => { + return await ctx.reply('Main Menu', Markup + .keyboard([ + ['😎 Профиль'], + ['🗄️ Работать', '🌐 Организация', '🎁 Бонус', '🏯 Казино'], + ['📦 Контейнеры'], + ['📢 Вакансии', '🔵 Имущество', '📞 Пригласить'] + ]) + .resize() + ) +}); + +bot.hears('Чат', async (ctx) => { + ctx.telegram.sendMessage(mainChat, `Automatic message`) +}); + +bot.hears('😎 Профиль', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + let property = await PropertyModel.findByPk(ctx.from.id); + if (!user) return ctx.reply(`Ошибка #1`); + return ctx.replyWithMarkdownV2(` + 👤${escape(user.username)} ${user.status == 'bronze' ? `\\[🔺\\]` : ""}${user.status == 'silver' ? `\\[🔹\\]` : ""}${user.status == 'gold' ? `\\[🔸\\]` : ""}${user.status == 'admin' ? "✅" : ""} + 🆔: ${ctx.from.id} + + 📶 Уровень: ${user.level} \\| ${user.exp} / ${expToUp[user.level]} + ⏩ Повышается за различные действия\\. + + 💰 Баланс + ¤${spacesWithMarkdown(user.money)} + + 🔵 Имущество + 🏠 Жилье: ${property.house == 0 ? "Бездомный" : property.house.name} + 🚗 Автомобиль: ${property.car == 0 ? "Пешком" : escape(property.car.name)} + 📱 Телефон: ${property.mobile == 0 ? "Нет" : property.mobile.name} + 🔫 Оружие: ${property.weapon == 0 ? "Безоружный" : property.weapon.name} + 🥼 Экипировка: ${property.equipment == 0 ? "Нет" : property.equipment.name} + `); + +}); + +bot.command('getprofile', async (ctx) => { + if(!ctx.message.reply_to_message) return await ctx.reply(`Только на пересланное сообщение.`) + let id = ctx.message.reply_to_message.from.id + let user = await UserModel.findByPk(id); + let property = await PropertyModel.findByPk(id); + return ctx.replyWithMarkdownV2(` + 👤${escape(user.username)} ${user.status == 'bronze' ? `\\[🔺\\]` : ""}${user.status == 'silver' ? `\\[🔹\\]` : ""}${user.status == 'gold' ? `\\[🔸\\]` : ""}${user.status == 'admin' ? "Administrator" : ""} + 🆔: ${ctx.from.id} + + 📶 Уровень: ${user.level} \\| ${user.exp} / ${expToUp[user.level]} + ⏩ Повышается за различные действия\\. + + 💰 Баланс + ¤${spacesWithMarkdown(user.money)} + + 🔵 Имущество + 🏠 Жилье: ${property.house == 0 ? "Бездомный" : property.house.name} + 🚗 Автомобиль: ${property.car == 0 ? "Пешком" : property.car.name} + 📱 Телефон: ${property.mobile == 0 ? "Нет" : property.mobile.name} + 🔫 Оружие: ${property.weapon == 0 ? "Безоружный" : property.weapon.name} + 🥼 Экипировка: ${property.equipment == 0 ? "Нет" : property.equipment.name} + `); + +}); + +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('🎁 Бонус', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + if (!user) return ctx.reply(`Ошибка #1`); + let bonustime = user.bonustime + let cooldown = setCooldown(user, 3600, bonustime) + if (user.bonustime > cooldown.currentTime) return ctx.reply(`📛 Забрать бонус можно будет через ${cooldown.timeLeftInMinutes} минут(у/ы)`); + user.bonus = 1; + user.bonustime = cooldown.endTime + let world = await WorldModel.findByPk(1) + let text = ``; + let money = [100, 200, 300, 400, 500, 1000].random(); + if (user.level >= 5) { + money += money; + } + let r = rand(1, 2); + let x = rand(2, 7); + if (r == 1) { + text += `⏩ ¤${money}\n`; + } + if (r == 2) { + money = money*x + text += `⏩ ¤${money}\n`; + } + switch(user.status){ + case 'bronze': + user.money += 5000 + text += `⭐ Дополнительный бонус за Bronze:\n⏩ ¤5.000\n` + break; + case 'silver': + user.money += 15000 + text += `⭐ Дополнительный бонус за Silver:\n⏩ ¤15.000\n` + break; + case 'gold': + user.money += 30000 + text += `⭐ Дополнительный бонус за Gold:\n⏩ ¤30.000\n` + break; + } + user.money += money; + world.balance -= money + if (user.business.id == 0){ + await user.save(); + await world.save(); + return ctx.reply(` + ⭐ Из ежечасного бонуса Вам выпало: +${text} + `) + } + let business = await BusinessModel.findOne({ + where: { + owner: user.business.id + } + }) + if(business != null){ + let mats = rand(3, 10) + switch(user.status){ + case 'bronze': + business.materials += 5 + text += `⭐ Дополнительный бонус за Bronze:\n⏩ 5 материалов\n` + break; + case 'silver': + business.materials += 10 + text += `⭐ Дополнительный бонус за Silver:\n⏩ 10 материалов\n` + break; + case 'gold': + business.materials += 20 + text += `⭐ Дополнительный бонус за Gold:\n⏩ 20 материалов\n` + break; + } + text += `⏩ ${mats} материалов в организацию\n` + business.materials += mats + business.save() + } + await user.save(); + await world.save(); + return ctx.reply(` + ⭐ Из ежечасного бонуса Вам выпало: +${text} + `) +}) + +bot.command('pay', async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`/pay [Никнейм] [Сумма]`) + if (!Number(ctx.args[2])) return ctx.reply(`❕ Сумма должна быть числовая.`) + let sender = await UserModel.findByPk(ctx.from.id); + let receiver = await UserModel.findOne({ + where: { + username: ctx.args[1] + } + }); + let world = await WorldModel.findByPk(1) + let fee = Number(Math.trunc(ctx.args[2] / 100 * world.transactionfee)) + if (ctx.args[2] == 0 || ctx.args[2] < 100) return ctx.reply(`❕ Минимальная сумма перевода ¤100.`) + if (sender.money < ctx.args[2]) return ctx.reply(`❕ Недостаточно средств!`) + if (sender.money < Number(ctx.args[2]) + fee) return ctx.reply(`❕ Недостаточно средств для перевода с комиссией!`) + sender.money -= Number(ctx.args[2]) + sender.money -= Number(fee) + world.balance += Number(fee) + await sender.save(); + await world.save(); + receiver.money += Number(ctx.args[2]) + await receiver.save(); + let pmToReceiver = `🔽 Входящий перевод.\n\n🔼 Отправитель: ${sender.username}\n🆔 Отправителя: ${sender.telegram_id}\n🔢 Сумма: ¤${ctx.args[2]}\n🆕 Ваш баланс: ¤${receiver.money} + ` + bot.telegram.sendMessage(receiver.telegram_id, pmToReceiver) + return ctx.reply(`🔼 Исходящий перевод.\n\n🔽 Получатель: ${receiver.username}\n🆔 Получателя: ${receiver.telegram_id}\n🔢 Сумма: ¤${ctx.args[2]}\nℹ️ Комиссия: ¤${fee}\n🆕 Ваш баланс: ¤${sender.money} + `) +}) + +bot.hears('Мир', async (ctx) => { + let world = await WorldModel.findByPk(1) + return ctx.reply(`🔰 Баланс мира: ¤${spaces(world.balance)}\nℹ️ Стоимость материалов: ¤${spaces(world.matPrice)} + `) +}) + +bot.hears('📞 Пригласить', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + return ctx.reply(` + ℹ️ Для приглашения друга по реферальной системе, отправьте ему ссылку-приглашение +Как только он перейдет по ней и начнет игру, Вы получите ¤25.000. + +Ваша ссылка: https://t.me/CampFireGameBot?start=${user.telegram_id} + `) +}) + +bot.hears('📢 Вакансии', async (ctx) => { + return await ctx.reply('Список работы', Markup + .inlineKeyboard([ + [{ + text: `Дворник [1 уровень]`, + callback_data: 'job_1' + }, { + text: `Промоутер [1 уровень]`, + callback_data: 'job_2' + }], [{ + text: `Официант [2 уровень]`, + callback_data: 'job_3' + }, { + text: `Бармен [3 уровень]`, + callback_data: 'job_4' + }], [{ + text: `Кассир [4 уровень] `, + callback_data: 'job_5' + }, { + text: `ПВЗ Дикие Ягоды [4 уровень]`, + callback_data: 'job_6' + }], [{ + text: `Слесарь [5 уровень]`, + callback_data: 'job_7' + }], [{ + text: `💤 Уволиться`, + callback_data: 'job_leave' + }] + ]) + .resize() + ) +}) + +bot.action(/job_(1|2|3|4|5|6|7|leave)/, async (ctx) => { + let data = ctx.update.callback_query.data; + let user = await UserModel.findByPk(ctx.from.id); + let job = null + switch(data){ + case `job_1`: + job = await JobModel.findByPk(1); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 1 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу дворником.\nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_2`: + job = await JobModel.findByPk(2); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 2 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу промоутером. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_3`: + job = await JobModel.findByPk(3); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 3 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу официантом. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_4`: + job = await JobModel.findByPk(4); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 4 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу барменом. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_5`: + job = await JobModel.findByPk(5); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 5 + user.save() + return await ctx.reply(`❕ Вы устроились на работу кассиром. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`ℹ️ Вы уже устроены на другую работу`) + case `job_6`: + job = await JobModel.findByPk(6); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 6 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу в ПВЗ Дикие Ягоды. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_7`: + job = await JobModel.findByPk(7); + if (user.level < job.level) { + return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) + } + if (user.job == 0) { + user.job = 7 + user.save() + return await ctx.reply(`ℹ️ Вы устроились на работу слесарем. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) + } + return await ctx.reply(`❕ Вы уже устроены на другую работу`) + case `job_leave`: + if (user.job != 0) { + user.job = 0 + user.save() + return await ctx.reply(`ℹ️ Теперь вы безработный.`) + } + return await ctx.reply(`❕ Вы итак безработный.`) + } +}) + +bot.hears('🏯 Казино', async (ctx) => { + return await ctx.reply('🏯 Добро пожаловать в казино "杜明"\n', Markup + .keyboard([ + ['🎰 Слоты'], + ['▶️ Меню'] + ]) + .resize() + ) +}) + +bot.hears('🗄️ Работать', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + let job = await JobModel.findByPk(user.job); + let world = await WorldModel.findByPk(1) + let timer = user.jobtime + let cooldown = setCooldown(user, 3600, timer) + if (user.jobtime > cooldown.currentTime) return ctx.reply(`📛 Работать можно будет через ${cooldown.timeLeftInMinutes} минут(у/ы)`); + if (user.job == 0) { + return await ctx.reply(`📛 Вы безработный.`) + } + user.jobtime = Number(cooldown.endTime) + let jobExp = job.exp; + user.jobcheck++ + switch (user.job) { + case 1: + if (user.jobcheck >= 4) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену дворника. \n🧾 Расчетный лист: \n⏳ Отработано часов: 4/4 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday}`) + } else { + user.save() + return ctx.reply(`👔 Вы подмели дворы. \n⏳ Отработано часов: ${user.jobcheck}/4`) + } + break; + case 2: + if (user.jobcheck >= 2) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену промоутера. \n🧾 Расчетный лист: \n⏳ Отработано часов: 2/2 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday}`) + } else { + user.save() + return ctx.reply(`👔 Вы раздавали листовки целый час. \n⏳ Отработано часов: ${user.jobcheck}/2`) + } + break; + case 3: + if (user.jobcheck >= 4) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + let tips = [50, 100, 200, 500, 1000].random() + user.money += tips + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену официанта. \n🧾 Расчетный лист: \n⏳ Отработано часов: 4/4 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday} \n💰 Получено чаевых: ¤${tips}`) + } else { + let tips = [50, 100, 200, 500, 1000].random() + user.money += tips + user.save() + return ctx.reply(`👔 Вы целый час бегали и отрабатывали заказы. \n🧾 Получено чаевых: ¤${tips} \n⏳ Отработано часов: ${user.jobcheck}/4`) + } + break; + case 4: + if (user.jobcheck >= 5) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + let tips = [50, 100, 200, 300, 500, 1000, 2000].random() + world.balance -= tips + user.money += tips + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену бармена. \n🧾 Расчетный лист: \n⏳ Отработано часов: 5/5 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday} \n💰 Получено чаевых: ¤${tips}`) + } else { + let tips = [50, 100, 200, 300, 500, 1000, 2000].random() + world.balance -= tips + user.money += tips + user.save() + world.save() + return ctx.reply(`👔 Вы целый час стояли за стойкой и разливали пойло. \n🧾 Получено чаевых: ¤${tips} \n⏳ Отработано часов: ${user.jobcheck}/5`) + } + break; + case 5: + if (user.jobcheck >= 5) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену кассира. \n🧾 Расчетный лист: \n⏳ Отработано часов: 5/5 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday}`) + } else { + user.save() + return ctx.reply(`👔 Вы целый час обслуживали покупателей и кричали: "Гаааляяя, отмена!". \n⏳ Отработано часов: ${user.jobcheck}/5`) + } + break; + case 6: + if (user.jobcheck >= 6) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + let stealed = [{ + name: "Помада", + price: 200 + }, { + name: "Бюстгалтер", + price: 1300 + }, { + name: "Прокладки", + price: 250 + }, { + name: "Перцовый балончик", + price: 600 + }, { + name: "Гитара", + price: 6500 + }, { + name: "Комбик", + price: 9000 + }, { + name: "Кроссовки", + price: 2000 + }, { + name: "Шампунь", + price: 180 + }, { + name: "Смартфон Texno", + price: 6999 + }, { + name: "TWS Гарнитура", + price: 2800 + }, { + name: "Геймпад GameStation 5", + price: 1400 + }, { + name: "Дилдо", + price: 600 + }, { + name: "Вагиноимитатор", + price: 600 + }].random() + world.balance -= payday + world.balance -= Number(stealed.price) + user.money += payday + user.money += Number(stealed.price) + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену в Диких Ягодах. \n🧾 Расчетный лист: \n⏳ Отработано часов: 6/6 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday} \n💰 Вы украли и продали со склада: ${stealed.name} (¤${stealed.price})`) + } else { + user.save() + return ctx.reply(`👔 Вы целый час выдавали заказы в Диких Ягодах. \n⏳ Отработано часов: ${user.jobcheck}/6`) + } + break; + case 7: + if (user.jobcheck >= 6) { + let paydayfee = job.salary / 100 * world.transactionfee + let payday = job.salary - paydayfee + world.balance -= payday + user.money += payday + giveExp(user, jobExp) + user.jobcheck = 0 + user.save() + world.save() + return ctx.reply(`👔 Вы отработали смену слесарем. \n🧾 Расчетный лист: \n⏳ Отработано часов: 6/6 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday}`) + } else { + user.save() + return ctx.reply(`👔 Вы целый час работали на заводе, вы молодец! \n⏳ Отработано часов: ${user.jobcheck}/6`) + } + break; + } +}) + +bot.hears('Топ', async (ctx) => { + let topPlayer = await UserModel.findAll({ + attributes: ['username', [sequelize.fn('sum', sequelize.col('money')), 'money'], 'status'], + group: ['username', 'status'], + where: { + telegram_id: { + [Op.ne]: 275416286 + } + }, + order: [ + [sequelize.literal('money'), 'DESC'] + ], + limit: 10 + }) + let text = `🏆 Топ 10 игроков по балансу.\n\n` + for(i=0; i { + let user = await UserModel.findByPk(ctx.from.id); + return await ctx.reply(`Выберите тип`, Markup + .inlineKeyboard([ + [ + {text: 'Жилье', callback_data: `shop_house`}, + {text: 'Телефоны', callback_data: `shop_phone`}, + {text: 'Автосалон', callback_data: `shop_car`} + ] + ]) + .resize()) +}) + +bot.action('shopmenu', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id); + return await ctx.editMessageText(`Выберите тип`, Markup + .inlineKeyboard([ + [ + {text: 'Жилье', callback_data: `shop_house`}, + {text: 'Телефоны', callback_data: `shop_phone`}, + {text: 'Автосалон', callback_data: `shop_car`} + ] + ]) + .resize()) +}) + +bot.action(/shop_(house|phone|car)/, async (ctx) => { + let data = ctx.update.callback_query.data; + let prodArray = [] + let text = `Доступно к покупке:\n` + switch(data){ + case `shop_house`: + for (i in houses) { + prodArray.push({text: i, callback_data: `{"action": "buy", "type": "house", "value": "${i}"}`}) + text += i + `. ${houses[i].name} (¤${houses[i].price})\n` + } + break; + case `shop_phone`: + for (i in phones) { + prodArray.push({text: i, callback_data: `{"action": "buy", "type": "phone", "value": "${i}"}`}) + text += i + `. ${phones[i].name} (¤${phones[i].price})\n` + } + break; + case `shop_car`: + for (i in cars) { + prodArray.push({text: i, callback_data: `{"action": "buy", "type": "car", "value": "${i}"}`}) + text += i + `. ${cars[i].name} (¤${cars[i].price})\n` + } + break; + } + prodArray.push({text: `Назад`, callback_data: `shopmenu`}) + let rows = [] + while (prodArray.length > 0) { + rows.push(prodArray.splice(0, 5)) // разбиваем на подмассивы по 5 кнопок + } + return await ctx.editMessageText(text, Markup + .inlineKeyboard(rows) + .resize()) +}) + +bot.action(/{"action": "buy"*/, async (ctx) => { + let data = ctx.update.callback_query.data; + data = JSON.parse(data) + let user = await UserModel.findByPk(ctx.from.id) + let property = await PropertyModel.findByPk(ctx.from.id); + let world = await WorldModel.findByPk(1) + if (data.type == "house") { + if (user.money < houses[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) + if (property.house.name) return await ctx.reply(`У вас уже есть дом.`) + user.money -= houses[data.value].price + world.balance += houses[data.value].price + property.house = houses[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${houses[data.value].name}`) + } + if (data.type == "car") { + if (user.money < cars[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) + if (property.car.name) return await ctx.reply(`У вас уже есть автомобиль.`) + if (!property.house.name) return await ctx.reply(`Для покупки автомобиля, у Вас должен быть дом.`) + user.money -= cars[data.value].price + world.balance += cars[data.value].price + property.car = cars[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${cars[data.value].name}`) + } + if (data.type == "phone") { + if (user.money < phones[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) + if (property.mobile.name) return await ctx.reply(`У вас уже есть телефон.`) + user.money -= phones[data.value].price + world.balance += phones[data.value].price + property.mobile = phones[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${phones[data.value].name}`) + } + if (data.type == "equipment") { + if (user.money < weaponshop[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) + if (data.type == weaponshop[data.value].type) { + if (property.equipment.name) return await ctx.reply(`У вас уже есть экипировка.`) + user.money -= weaponshop[data.value].price + world.balance += weaponshop[data.value].price + property.equipment = weaponshop[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${weaponshop[data.value].name}`) + } + if (property.weapon.name) return await ctx.reply(`У вас уже есть оружие.`) + user.money -= weaponshop[data.value].price + world.balance += weaponshop[data.value].price + property.weapon = weaponshop[data.value] + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы купили ${weaponshop[data.value].name}`) + } +}) + +bot.hears('Поставщик', async (ctx) => { + let text = `[Hatkeis Gunsmith](https://telegra.ph/Hatkeis-Gunsmith-09-27)` + let shop = `\n Вы подходите к зданию с вывеской "Ништяки Хаткейса".\n Вот ассортимент на сегодня\n` + for (i = 0; i < 10; i++) { + shop += `${i}. ${weaponshop[i].name} (¤${spaces(weaponshop[i].price)})\n` + } + weaponShopUpdate() + return await ctx.replyWithMarkdownV2(text + escape(shop), {disable_web_page_preview: true}) +}) + +bot.command('sell', async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + let user = await UserModel.findByPk(ctx.from.id) + let property = await PropertyModel.findByPk(ctx.from.id); + let world = await WorldModel.findByPk(1) + if (!ctx.args[1]) return ctx.reply(`Не указан аргумент.`) + if (ctx.args[1] == "house") { + if (!property.house.name) return await ctx.reply(`У вас нет дома.`) + let name = property.house.name + user.money += Math.round(property.house.price/2) + world.balance -= Math.round(property.house.price/2) + property.house = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } + if (ctx.args[1] == "car") { + if (!property.car.name) return await ctx.reply(`У вас нет автомобиля.`) + let name = property.car.name + user.money += Math.round(property.car.price/2) + world.balance -= Math.round(property.car.price/2) + property.car = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } + if (ctx.args[1] == "phone") { + if (!property.mobile.name) return await ctx.reply(`У вас нет телефона.`) + let name = property.mobile.name + user.money += Math.round(property.mobile.price/2) + world.balance -= Math.round(property.mobile.price/2) + property.mobile = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } + if (ctx.args[1] == "equipment") { + if (!property.equipment.name) return await ctx.reply(`У вас нет экипировки.`) + let name = property.equipment.name + user.money += Math.round(property.equipment.price/2) + world.balance -= Math.round(property.equipment.price/2) + property.equipment = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } + if (ctx.args[1] == "weapon") { + if (!property.weapon.name) return await ctx.reply(`У вас нет оружия.`) + let name = property.weapon.name + user.money += Math.round(property.weapon.price/2) + world.balance -= Math.round(property.weapon.price/2) + property.weapon = 0 + await user.save() + await world.save() + await property.save() + return await ctx.reply(`Вы продали ${name}`) + } +}) + +bot.hears('🌐 Организация', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if(business === null){ + business = await BusinessModel.findOne({ + where: { + owner: user.business.id + } + }) + return await ctx.replyWithMarkdownV2(`🏭 Организация\n_${business.name}_\n💹 Баланс: ¤${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n\nВаши отработки: ${user.business.checks}`, Markup.inlineKeyboard([ + [{ + text: `📶 Отработка`, + callback_data: "workoff" + }, { + text: `⬅️ Покинуть`, + callback_data: "покинуть" + }] + ]) + .oneTime() + .resize()) + } + if (business.owner == ctx.from.id){ + return await ctx.replyWithMarkdownV2(`🏭 Ваша организация\n_${business.name}_\n💹 Баланс: ¤${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n🔨 Отработок: ${business.checks}\n\nВаши отработки: ${user.business.checks}`, Markup.inlineKeyboard([ + [{ + text: `📶 Отработка`, + callback_data: "workoff" + }, { + text: `💸 Payday`, + callback_data: "payday" + }] + ]) + .oneTime() + .resize()) + } +}) + +bot.action('workoff', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let business = await BusinessModel.findOne({ + where: { + owner: user.business.id.toString() + } + }) + if (user.business == null) return await ctx.reply(`Вы не работаете в организации.`) + let timer = user.worktime + let cooldown = setCooldown(user, 3600, timer) + if (user.worktime > cooldown.currentTime) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `📛 Работа в организации будет доступна через ${cooldown.timeLeftInMinutes} минут(у/ы)`, {show_alert: true}); + if (business.materials < 10) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `📛 В организации недостаточно материалов для отработки.`); + user.worktime = cooldown.endTime + user.business = { + id: user.business.id, + checks: user.business.checks + 1, + percent: user.business.percent + } + business.materials -= 10 + business.checks += 1 + await user.save() + await business.save() + if (business.owner == ctx.from.id){ + return await ctx.editMessageText(`🏭 Ваша организация\n_${business.name}_\n💹 Баланс: ¤${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials} \n👥 Рабочих: ${business.users.length}\n🔨 Отработок: ${business.checks}\n\nВаши отработки: ${user.business.checks}`, + { + reply_markup: { + inline_keyboard: [ + [{ + text: `📶 Отработка`, + callback_data: "workoff" + }, { + text: `💸 Payday`, + callback_data: "payday" + }] + ]}, + parse_mode: `MarkdownV2` + } + ) + }else{ + return await ctx.editMessageText(`🏭 Организация\n_${business.name}_\n💹 Баланс: ¤${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n\nВаши отработки: ${user.business.checks}`, + { + reply_markup: { + inline_keyboard: [ + [{ + text: `📶 Отработка`, + callback_data: "workoff" + }, { + text: `⬅️ Покинуть`, + callback_data: "покинуть" + }] + ]}, + parse_mode: `MarkdownV2` + } + ) + } +}) + +bot.action('покинуть', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if(business === null){ + business = await BusinessModel.findOne({ + where: { + owner: user.business.id + } + }) + await ctx.reply(`Подтвердите в личных сообщениях.`) + return await bot.telegram.sendMessage(ctx.from.id, `🏭 Вы действительно хотите покинуть ${business.name}`, Markup.inlineKeyboard([ + [{ + text: `Да`, + callback_data: "user_leave_business" + }, { + text: `Нет`, + callback_data: "cancel" + }] + ]) + .oneTime() + .resize() + ) + } + if (business.owner == ctx.from.id){ + return await ctx.reply(`Вы не можете покинуть свою организацию.`) + } +}) + +bot.action('cancel', async (ctx) => { + await ctx.deleteMessage() + await bot.telegram.answerCbQuery(ctx.callbackQuery.id, `Отмена.`) +}) + +bot.action('user_leave_business', async (ctx) => { + let data = ctx.update.callback_query.data; + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) + let business = await BusinessModel.findOne({ + where: { + owner: user.business.id + } + }) + user.business = { + id: 0, + checks: 0, + percent: 0 + } + business.users = business.users.filter(value => value != ctx.from.id); + business.save() + user.save() + return await bot.telegram.sendMessage(ctx.from.id, `🏭 Вы покинули ${business.name}`) +}) + +bot.action('payday', async (ctx) => { + let user = null + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + let world = await WorldModel.findByPk(1) + if (business === null) return await ctx.reply(`У вас нет организации.`) + if (business.checks < 12) return await ctx.reply(`Недостаточно отработок для формирования выплаты.`) + let percentSum = 0 + let text = `` + let percentErrorText = `` + let profit = 0 + let piece = 0 + let moneyList = rand(1000, 3000) + moneyList = moneyList*business.users.length + for (i = 0; i < business.users.length; i++) { // Summary percent + user = await UserModel.findByPk(business.users[i]) + percentSum += Number(user.business.percent) + percentErrorText += `ℹ️ ${user.username} ${user.business.percent}% [/percent ${user.username} [проценты]]\n` + } + if (percentSum > 100) return await ctx.reply(`⚠️ Общий процент всех сотрудников превышает 100%\n ➕ Остаток процентов перенесется в баланс организации.\n\n${percentErrorText}\n`) + for (x = 0; x < business.users.length; x++) { // Общая внесенная сумма всеми участниками + user = await UserModel.findByPk(business.users[x]) + profit += user.business.checks * moneyList * user.level + text += `ℹ️ ${user.username} отработал ${user.business.checks} раз.\n` + user.business = { + id: user.business.id, + checks: 0, + percent: user.business.percent + } + user.save() + } + text += ` 💹 Наработка за текущий период: ${profit}\n` + let profitCheck = profit + for (n = 0; n < business.users.length; n++) { // Процент выплаты участникам + user = await UserModel.findByPk(business.users[n]) + piece = Math.round(profit / 100 * user.business.percent) + profitCheck -= piece + user.money += piece + text += `➕ ${user.username} получает ¤${piece}\n` + await bot.telegram.sendMessage(user.telegram_id, `ℹ️ Директор организации сформировал выплаты.\n➕ На ваш баланс поступило: ${spaces(piece)}`) + giveExp(user, business.checks) + user.save() + } + if (profitCheck > 0) { + business.balance += profitCheck + text += `➕ На баланс бизнеса поступило ¤${profitCheck}` + } + business.checks = 0 + business.save() + console.log(`Payday: ${business.name}\n${text}`) + return await ctx.reply(text) +}) + +bot.command('orgmessage', async (ctx) => { + if (!ctx.args[1]) return ctx.reply(`Не указан аргумент.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if (business === null) return await ctx.reply(`У вас нет организации.`) + for (i = 0; i < business.users.length; i++) { + user = await UserModel.findByPk(business.users[i]) + await bot.telegram.sendMessage(user.telegram_id, `Директор организации сообщает:\n ${ctx.payload}`) + } + console.log(`Директор организации сообщает:\n ${ctx.payload}`) + return await ctx.reply(`Сообщение отправлено.`) +}) + +bot.command('materials', async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`🚫 Вы не владеете организацией.`) + let world = await WorldModel.findByPk(1) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if (business === null) return await ctx.reply(`🚫 У вас нет организации.`) + if (!ctx.args[1]) return ctx.reply(`🚫 Не указан аргумент.`) + if (!Number(ctx.args[1])) return ctx.reply(`ℹ️ Количество должно быть числом.`) + if (ctx.args[1] < 1) return ctx.reply(`ℹ️ Минимальное количество для покупки - 1`) + if (ctx.args[1]*world.matPrice > business.balance) return ctx.reply(`🚫 Недостаточно средств на балансе организации.`) + if (business.materials >= 700) return ctx.reply(`🚫 Склады полны.`) + if (business.materials + Number(ctx.args[1]) > 700) return ctx.reply(`🚫 Нет столько места на складах.\n Можно закупить еще ${700 - business.materials}`) + let count = Number(ctx.args[1]) + business.balance -= world.matPrice*count + business.materials += count + business.save() + return await ctx.reply(`➕ Закуплено ${ctx.args[1]} материалов для организации на сумму ¤${world.matPrice*count}`) +}) + +bot.command('percent', async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`Вы не владеете организацией.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if (business === null) return await ctx.reply(`У вас нет организации.`) + if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`Не указан аргумент.`) + if (!Number(ctx.args[2])) return ctx.reply(`Процент должен быть числом от 1 до 100.`) + if (ctx.args[2] < 1 || ctx.args[2] > 100) return ctx.reply(`Минимальный процент 1 | Максимальный процент 100.`) + ctx.args[1] = ctx.args[1] + console.log(ctx.args) + let change = await UserModel.findOne({ + where: { + username: ctx.args[1] + } + }) + if (change === null) return await ctx.reply(`Нет такого игрока.`) + change.business = { + id: change.business.id, + checks: change.business.checks, + percent: ctx.args[2] + } + change.save() + return await ctx.reply(`Участнику ${change.username} установлен процент ${ctx.args[2]}`) +}) + +bot.command('business', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id != 0){ + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + } + let business = null + let world = await WorldModel.findByPk(1) + ctx.args = ctx.update.message.text.split(' ') + if (business != null) return await ctx.reply(`У вас уже есть организация.`) + if (!ctx.args[1]) return ctx.reply(`/business [Название организации]`) + if (user.money < 100000) return await ctx.reply(`Регистрация организации стоит ¤100.000`) + if (user.level < 5) return await ctx.reply(`Регистрация организации доступна с 5 уровня.`) + user.money -= 100000 + world.balance += 100000 + let text = `` + for (i = 1; i < ctx.args.length; i++) { + text += `${ctx.args[i]} ` + } + if (business === null) { + BusinessModel.create({ + name: text, + owner: user.telegram_id, + balance: 50000, + users: [user.telegram_id] + }) + user.business = { + id: user.telegram_id, + checks: 0, + percent: 100 + } + } else {} + user.save() + world.save() + return await ctx.reply(`Организация "${text}" успешно создана!\n Регистрация организации в реестре: ¤50.000 \n Капитал: ¤50.000`) +}) + +bot.command('invite', async (ctx) => { + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1]) return ctx.reply(`/invite [Nick]`) + let user = await UserModel.findByPk(ctx.from.id) + if (user.business.id == 0) return await ctx.reply(`🚫 У вас нет организации в которую можно пригласить игрока.`) + let business = await BusinessModel.findOne({ + where: { + owner: ctx.from.id.toString() + } + }) + if (business.users.length >= 5) return await ctx.reply(`📛 Достигнуто максимальное количество сотрудников в организации.`) + let invited = await UserModel.findOne({ + where: { + username: ctx.args[1] + } + }); + await bot.telegram.sendMessage(invited.telegram_id, '⤵️ Приглашение', Markup + .inlineKeyboard([ + [{ + text: `Принять`, + callback_data: `{"type": "business_invite_accept", "invitor": "${user.telegram_id}"}` + }, { + text: `Отклонить`, + callback_data: `{"type": "business_invite_refuse", "invitor": "${user.telegram_id}"}` + }] + ]).oneTime()) + return await ctx.reply(`Приглашение отправлено.`) +}) + +bot.action(/{"type": "business_invite_(accept|refuse)"*/, async ctx => { + let data = ctx.update.callback_query.data; + data = JSON.parse(data) + let user = await UserModel.findByPk(ctx.update.callback_query.from.id) + if (data.type == 'business_invite_accept') { + if(user.business.id == 0){ + let business = await BusinessModel.findOne({ + where: { + owner: data.invitor + } + }) + user.business = { + id: data.invitor, + checks: 0, + percent: 10 + } + business.users = sequelize.fn('array_append', sequelize.col('users'), ctx.update.callback_query.from.id); + business.save() + user.save() + await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `✔️ Приглашение принято.`, {show_alert: true}) + } + await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `ℹ️ Вы уже в организации.`, {show_alert: true}) + } + if (data.type == 'business_invite_refuse'){ + await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `❌ Приглашение отклонено.`, {show_alert: true}) + } +}) + +bot.command('report', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1]) return ctx.reply(`/report [Текст обращения]`) + let uID = shortid.generate() + await ReportModel.create({ + uid: uID, + author: user.telegram_id, + text: ctx.payload, + status: 1 + }) + let report = await ReportModel.findOne({ + where: { + uid: uID + } + }) + await bot.telegram.sendMessage(adminList[0], `Обращение от пользователя ${user.username}\nТекст обращения:\n${ctx.payload}\n\nДля ответа /answer ${report.id} [Ответ]`) + return await ctx.reply(`Обращение #${report.id}[${report.uid}] создано.`) +}) + +bot.hears('🎰 Слоты', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + ctx.args = ctx.update.message.text.split(' ') + await ctx.reply('Комбинации слотов:\n7️⃣7️⃣7️⃣ - x25\n🍋🍋🍋 - x20\n🍇🍇🍇 - x15\n🔤🔤🔤 - x10', Markup + .inlineKeyboard([ + [{ + text: `1000`, + callback_data: `slots1000` + }, { + text: `5000`, + callback_data: `slots5000` + }, { + text: `25000`, + callback_data: `slots25000` + }, { + text: `50000`, + callback_data: `slots50000` + }, { + text: `100000`, + callback_data: `slots100000` + }] + ])) +}) + +bot.action(/slots(1000|5000|25000|50000|100000)/, async (ctx) => { + let data = ctx.update.callback_query.data; + let bet = 1000 + switch(data){ + case `slots1000`: + bet = 1000 + break; + case `slots5000`: + bet = 5000 + break; + case `slots25000`: + bet = 25000 + break; + case `slots50000`: + bet = 50000 + break; + case `slots100000`: + bet = 100000 + break; + } + let user = await UserModel.findByPk(ctx.from.id) + let timer = user.slottime + let cooldown = setCooldown(user, 10, timer) + if (user.slottime > cooldown.currentTime) return ctx.reply(`📛 Слоты будут доступны через пару секунд`); + if (user.money < bet) return ctx.reply(`Недостаточно средств.`) + user.slottime = cooldown.endTime + let world = await WorldModel.findByPk(1) + let result = await ctx.replyWithDice({emoji: `🎰`}) + let slot = slots[result.dice.value] + let win = getSlot(result) + console.log(user.username + `: Win: x` + win) + user.money -= bet + world.balance += bet + if(win > 4){ + user.world -= bet*win + user.money += bet*win + user.save() + world.save() + return setTimeout(() => { + ctx.reply(`➕ Вы выиграли ¤${spaces(bet*win)}`) + }, 1700); + } + if(win > 0 && win <= 4){ + await giveExp(user, win*2) + return setTimeout(() => { + ctx.reply(`➕ Вы выиграли ${win*2} опыта.`) + }, 1700); + } + if(win == 0){ + return setTimeout(() => { + world.save() + user.save() + ctx.reply(`➖ Вы проиграли ¤${spaces(bet)}.`) + }, 1700); + } + +}) + +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', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1]) return ctx.reply(`/promocode [Code]`) + let promocode = await PromocodeModel.findOne({ + where: { + code: ctx.args[1] + } + }) + if(promocode === null) return await ctx.reply(`➖ Нет такого кода.`) + if(promocode.users.length-1 >= promocode.activations && promocode.users != null) return await ctx.reply(`⚠️ Промокод уже активировали максимальное количество раз.`) + if(promocode.users.includes(ctx.from.id.toString())) return await ctx.reply(`⚠️ Вы уже активировали этот промокод.`) + console.log(promocode.users) + promocode.users = sequelize.fn('array_append', sequelize.col('users'), ctx.from.id.toString()); + user.money += promocode.money + user.save() + promocode.save() + await bot.telegram.sendMessage(adminList[0], `${user.username} активировал промокод.`) + return await ctx.reply(`✅ Вы активировали промокод.`) +}) + +bot.hears('📦 Контейнеры', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let containers = [] + let superWin = rarecars.random() + let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + let oneValue = [] + for(i = 0; i < 10; i++){ + oneValue = values.random() + values = values.filter(value => value != oneValue); + containers.push({name: `📦 Контейнер ${i+1}`, value: oneValue}) + } + let keyboardButtons = containers.map(container => { + return {text: container.name, callback_data: `container_${container.value}`} + }) + let rows = [] + while (keyboardButtons.length > 0) { + rows.push(keyboardButtons.splice(0, 2)) // разбиваем на подмассивы по 5 кнопок + } + await ctx.replyWithMarkdownV2('[Sueta Logistic International](https://telegra.ph/OOO-Sueta-Logistic-International-09-27)\nДоступные контейнеры в порту:', + { + reply_markup: { + inline_keyboard: rows + }, + disable_web_page_preview: true + }) +}) + + +bot.action(/container_(1|2|3|4|5|6|7|8|9|10)/, async (ctx) => { + let data = ctx.update.callback_query.data; + let user = await UserModel.findByPk(ctx.from.id) + let property = await PropertyModel.findByPk(ctx.from.id) + if(user.money < 500000) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Открытие контейнера стоит ¤500.000`, {show_alert: true}) + if(property.car.name) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас уже есть автомобиль\nПродайте текущий автомобиль: /sell car`, {show_alert: true}) + user.money -= 500000 + let userWin = null + switch(data){ + case `container_7`: + userWin = rarecars.random() + break; + default: + userWin = simplecars.random() + break; + } + property.car = userWin + user.save() + property.save() + ctx.deleteMessage() + return await ctx.sendPhoto(userWin.image, { caption: `В контейнере была: ${userWin.name} стоимостью ¤${spaces(userWin.price)}`}) +}) + +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() +}) +/////////////////////////////////////Admin Commands////////////////////////////////////////////////// + + +bot.command('answer', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if(user.status != 'admin') return await ctx.reply(`Admin Only.`) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1]) return ctx.reply(`Нужен номер обращения`) + let report = await ReportModel.findByPk(ctx.args[1]) + if (report === null) return await ctx.reply(`Нет обращения с таким ID.`) + if (report.status == 0) return await ctx.reply(`Данное обращение уже закрыто.`) + let answer = ctx.args + answer.shift() + answer.shift() + answer = answer.join(' ') + await bot.telegram.sendMessage(report.author, `Ответ на обращение #${report.id}[${report.uid}]\n\n` + answer) + report.status = 0 + report.save() + return await ctx.reply(`Ответ отправлен, обращение закрыто!`) +}) + +bot.command('fastblock', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if(!ctx.message.reply_to_message) return await ctx.reply(`Только на пересланное сообщение.`) + let blocked = ctx.message.reply_to_message.from.id + 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(`Пользователь заблокирован.`) +}) + +bot.command('createpromocode', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if(user.status != 'admin') return await ctx.reply(`Admin Only.`) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1] || !ctx.args[2] || !ctx.args[3]) return ctx.reply(`/createpromo [activations] [money] [code]`) + let promocode = await PromocodeModel.findOne({ + where: { + code: ctx.args[3] + } + }) + if(promocode === null){ + await PromocodeModel.create({ + code: ctx.args[3], + activations: ctx.args[1], + money: ctx.args[2] + }) + let voucherImage = await generateVoucher(ctx.args[3], ctx.args[1], ctx.args[2]) + return await ctx.sendPhoto({source: voucherImage, caption: `Создан промокод ${ctx.args[3]}` }) +} +}) + +bot.command('genpromo', async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + if(user.status != 'admin') return await ctx.reply(`Admin Only.`) + ctx.args = ctx.update.message.text.split(' ') + if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`/genpromo [activations] [money]`) + let code = voucher_codes.generate({ + length: 6, + count: 1, + prefix: "CMP-", + postfix: "-FIRE", + charset: voucher_codes.charset("alphanumeric") + }); + let promocode = await PromocodeModel.findOne({ + where: { + code: code[0] + } + }) + if(promocode === null){ + await PromocodeModel.create({ + code: code[0], + activations: ctx.args[1], + money: ctx.args[2] + }) + let voucherImage = await generateVoucher(code, ctx.args[1], ctx.args[2]) + return await ctx.sendPhoto({source: voucherImage, caption: `Создан промокод ${code[0]}` }) +} +}) + +///////////////////////////////////////Functions////////////////////////////////////////////////////// + +function rand(min, max) { + return Math.round(Math.random() * (max - min)) + min +} +var parserInt = (str) => parseInt(str.replace(/k|к/ig, "000")); + +function spaces(string) { + if (typeof string !== "string") string = string.toString(); + return string.split("").reverse().join("").match(/[0-9]{1,3}/g).join(".").split("").reverse().join(""); +}; +function spacesWithMarkdown(string) { + if (typeof string !== "string") string = string.toString(); + return string.split("").reverse().join("").match(/[0-9]{1,3}/g).join(".\\").split("").reverse().join(""); +}; +function escape(text) { + text = text + .replace(/\_/g, '\\_') + .replace(/\*/g, '\\*') + .replace(/\[/g, '\\[') + .replace(/\]/g, '\\]') + .replace(/\(/g, '\\(') + .replace(/\)/g, '\\)') + .replace(/\~/g, '\\~') + .replace(/\`/g, '\\`') + .replace(/\>/g, '\\>') + .replace(/\#/g, '\\#') + .replace(/\+/g, '\\+') + .replace(/\-/g, '\\-') + .replace(/\=/g, '\\=') + .replace(/\|/g, '\\|') + .replace(/\{/g, '\\{') + .replace(/\}/g, '\\}') + .replace(/\./g, '\\.') + .replace(/\!/g, '\\!'); + return text +}; +Array.prototype.random = function() { + return this[Math.floor(this.length * Math.random())]; +} + +function getCurrentTime() { + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth() < 9 ? `0${now.getMonth() + 1}` : now.getMonth() + 1; + const day = now.getDate() < 10 ? `0${now.getDate()}` : now.getDate(); + const hours = now.getHours() < 10 ? `0${now.getHours()}` : now.getHours(); + const minutes = now.getMinutes() < 10 ? `0${now.getMinutes()}` : now.getMinutes(); + const seconds = now.getSeconds() < 10 ? `0${now.getSeconds()}` : now.getSeconds(); + return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`; +} + +function getSlot(result) { + switch(result.dice.value){ + case 1: + return 10 + case 22: + return 15 + case 43: + return 20 + case 64: + return 25 + case 17: case 33: case 49: + return 1 + case 6: case 38: case 54: + return 2 + case 11: case 27: case 59: + return 3 + case 16: case 32: case 48: + return 4 + default: + return 0 +}} + +function setCooldown(user, seconds, type) { + let cooldown = {} + cooldown.currentTime = Math.trunc(Date.now() / 1000) + + switch(user.status){ + case `user`: + cooldown.endTime = Math.trunc(Date.now() / 1000 + seconds) + break; + case `bronze`: + cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*85)) + break; + case `silver`: + cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*75)) + break; + case `gold`: + cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*50)) + break; + case `admin`: + cooldown.endTime = Math.trunc(Date.now() / 1000) + break; + } + cooldown.timeLeft = cooldown.endTime - cooldown.currentTime + cooldown.timeLeftInMinutes = Math.ceil((type - cooldown.currentTime) / 60) + return cooldown +} + +async function giveExp(user, experience) { + user.exp += experience + for(i in expToUp){ + if (user.exp >= expToUp[user.level]) { + user.exp -= expToUp[user.level] + user.level += 1 + user.save() + await bot.telegram.sendMessage(user.telegram_id, `⤴️ Ваш уровень повысился до ${user.level}!`)} + } + user.save() +} + +function weaponShopUpdate() { + let weaponId = [] + let equipId = [] + let drop = 1 + let counter = 5 + for (i = 0; i < 5; i++) { + drop = weaponId.push(rand(1, 10)) + } + for (i = 0; i < 5; i++) { + drop = equipId.push(rand(1, 10)) + } + for (i = 0; i < 5; i++) { + weaponshop[i] = weapons[weaponId[i]] + } + for (i = 0; i < 5; i++) { + weaponshop[counter] = equipment[equipId[i]] + counter++ + } + fs.writeFileSync('json/weaponshop.json', JSON.stringify(weaponshop, null, "\t")) +} + +async function matPriceUpdate() { + let world = await WorldModel.findByPk(1) + let price = rand(35, 170) + world.matPrice = price + world.save() +} + +setTimeout(() => { + generatePromo() +}, 360000*3); + +setInterval(() => { + var today = new Date(); + let hours = today.getHours(); + if (hours == "0" || hours == "12") { + weaponShopUpdate() + matPriceUpdate() + } +}, 360000); + +async function generatePromo() { + let activs = rand(1, 3) + let give = rand(1000, 10000) + let code = voucher_codes.generate({ + length: 6, + count: 1, + prefix: "CMP-", + postfix: "-FIRE", + charset: voucher_codes.charset("alphanumeric") + }); + let promocode = await PromocodeModel.findOne({ + where: { + code: code[0] + } + }) + if(promocode === null){ + await PromocodeModel.create({ + code: code[0], + activations: activs, + money: give + }) + let voucherImage = await generateVoucher(code[0], activs, give) + return await bot.telegram.sendPhoto(mainChat, {source: voucherImage}) +} +} + +async function generateVoucher(code, activations, money) { + // загружаем изображение фона + const background = await loadImage('./media/imageDefault3.png'); + + // создаем новый canvas + const canvas = createCanvas(background.width, background.height); + const ctx = canvas.getContext('2d'); + + // рисуем фоновое изображение + ctx.drawImage(background, 0, 0); + + // выводим текст на картинку + ctx.font = 'bold 30px Srbija Sans'; + ctx.fillStyle = '#232323'; + ctx.textAlign = 'center'; + ctx.fillText(`${code}`, canvas.width/2, canvas.height/1.90); + + // сохраняем картинку в файл + const out = fs.createWriteStream('./media/image.png'); + const stream = canvas.createPNGStream(); + stream.pipe(out); + + // возвращаем путь к сгенерированной картинке + return './media/image.png'; + } + +start() + +bot.launch() \ No newline at end of file diff --git a/index.js b/index.js index a54b701..a73d4ca 100644 --- a/index.js +++ b/index.js @@ -1,1763 +1,2 @@ require('dotenv').config() -const { - Telegraf, - Markup -} = require('telegraf') -const shortid = require('shortid'); -const voucher_codes = require('voucher-code-generator'); -const { createCanvas, loadImage } = require('canvas'); -const fs = require('fs') -const bot = new Telegraf(process.env.BOT_TOKEN) -const weaponshop = require('./json/weaponshop.json') -const slots = require('./json/slots.json') -const rarecars = require('./json/rarecars.json') -const simplecars = require('./json/simplecars.json') -const houses = require('./presets/houses.json') -const cars = require('./presets/cars.json') -const phones = require('./presets/mobiles.json') -const weapons = require('./presets/weapons.json') -const equipment = require('./presets/equipment.json') -const sequelize = require('./db'); -const { Op } = require('sequelize'); -const UserModel = require('./models/user.model'); -const WorldModel = require('./models/world.model'); -const JobModel = require('./models/job.model'); -const PropertyModel = require('./models/property.model'); -const BusinessModel = require('./models/business.model'); -const ReportModel = require('./models/report.model'); -const BlockModel = require('./models/block.model'); -const PromocodeModel = require('./models/promocode.model'); -const mainChat = -1001895132127 -const adminList = [275416286] -const expToUp = [0, 10, 20, 40, 60, 100, 250, 370, 450, 575, 666, 777, 860, 999, 1000, 1177, 1234, 1350, 1488, 1515, 1610] -const topSym = ['🥇', '🥈', '🥉', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'] - -const start = async () => { - try { - await sequelize.authenticate() - await sequelize.sync() - } catch (e) { - console.log('Подключение к бд сломалось', e) - } -} - -bot.telegram.setMyCommands([{ - command: "pay", - description: "Перевести указанному пользователю сумму." - }, - { - command: "buy", - description: "Приобрести указанное имущество." - }, - { - command: "business", - description: "Создать организацию." - }, - { - command: "invite", - description: "Пригласить пользователя в организацию." - }, - { - command: "percent", - description: "Установить пользователю процент заработка." - }, - { - command: "report", - description: "Создать жалобу/обращение/идею." - } -]) - -bot.use(async (ctx, next) => { - let id = ctx.from.id - let username = ctx.from.username - if(username == null) username = ctx.from.id - try { - console.log(getCurrentTime() + `: ` + username + `: ` + ctx.update.message.text) - } catch (e) { - console.log(getCurrentTime() + `: ${username}: ${ctx.update.callback_query.data}`) - } - let user = await UserModel.findByPk(id); - let block = await BlockModel.findByPk(id); - let property = await PropertyModel.findByPk(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 - }) - } else {} - //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() - return next().then(() => { - const ms = Date.now() - start - console.log('response time %sms', ms) - }) -}) - -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) => { - return await ctx.reply('Main Menu', Markup - .keyboard([ - ['😎 Профиль'], - ['🗄️ Работать', '🌐 Организация', '🎁 Бонус', '🏯 Казино'], - ['📦 Контейнеры'], - ['📢 Вакансии', '🔵 Имущество', '📞 Пригласить'] - ]) - .resize() - ) -}); - -bot.hears('Чат', async (ctx) => { - ctx.telegram.sendMessage(mainChat, `Automatic message`) -}); - -bot.hears('😎 Профиль', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id); - let property = await PropertyModel.findByPk(ctx.from.id); - if (!user) return ctx.reply(`Ошибка #1`); - return ctx.replyWithMarkdownV2(` - 👤${escape(user.username)} ${user.status == 'bronze' ? `\\[🔺\\]` : ""}${user.status == 'silver' ? `\\[🔹\\]` : ""}${user.status == 'gold' ? `\\[🔸\\]` : ""}${user.status == 'admin' ? "✅" : ""} - 🆔: ${ctx.from.id} - - 📶 Уровень: ${user.level} \\| ${user.exp} / ${expToUp[user.level]} - ⏩ Повышается за различные действия\\. - - 💰 Баланс - ¤${spacesWithMarkdown(user.money)} - - 🔵 Имущество - 🏠 Жилье: ${property.house == 0 ? "Бездомный" : property.house.name} - 🚗 Автомобиль: ${property.car == 0 ? "Пешком" : property.car.name} - 📱 Телефон: ${property.mobile == 0 ? "Нет" : property.mobile.name} - 🔫 Оружие: ${property.weapon == 0 ? "Безоружный" : property.weapon.name} - 🥼 Экипировка: ${property.equipment == 0 ? "Нет" : property.equipment.name} - `); - -}); - -bot.command('getprofile', async (ctx) => { - if(!ctx.message.reply_to_message) return await ctx.reply(`Только на пересланное сообщение.`) - let id = ctx.message.reply_to_message.from.id - let user = await UserModel.findByPk(id); - let property = await PropertyModel.findByPk(id); - return ctx.replyWithMarkdownV2(` - 👤${escape(user.username)} ${user.status == 'bronze' ? `\\[🔺\\]` : ""}${user.status == 'silver' ? `\\[🔹\\]` : ""}${user.status == 'gold' ? `\\[🔸\\]` : ""}${user.status == 'admin' ? "Administrator" : ""} - 🆔: ${ctx.from.id} - - 📶 Уровень: ${user.level} \\| ${user.exp} / ${expToUp[user.level]} - ⏩ Повышается за различные действия\\. - - 💰 Баланс - ¤${spacesWithMarkdown(user.money)} - - 🔵 Имущество - 🏠 Жилье: ${property.house == 0 ? "Бездомный" : property.house.name} - 🚗 Автомобиль: ${property.car == 0 ? "Пешком" : property.car.name} - 📱 Телефон: ${property.mobile == 0 ? "Нет" : property.mobile.name} - 🔫 Оружие: ${property.weapon == 0 ? "Безоружный" : property.weapon.name} - 🥼 Экипировка: ${property.equipment == 0 ? "Нет" : property.equipment.name} - `); - -}); - -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('🎁 Бонус', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id); - if (!user) return ctx.reply(`Ошибка #1`); - let bonustime = user.bonustime - let cooldown = setCooldown(user, 3600, bonustime) - if (user.bonustime > cooldown.currentTime) return ctx.reply(`📛 Забрать бонус можно будет через ${cooldown.timeLeftInMinutes} минут(у/ы)`); - user.bonus = 1; - user.bonustime = cooldown.endTime - let world = await WorldModel.findByPk(1) - let text = ``; - let money = [100, 200, 300, 400, 500, 1000].random(); - if (user.level >= 5) { - money += money; - } - let r = rand(1, 2); - let x = rand(2, 7); - if (r == 1) { - text += `⏩ ¤${money}\n`; - } - if (r == 2) { - money = money*x - text += `⏩ ¤${money}\n`; - } - switch(user.status){ - case 'bronze': - user.money += 5000 - text += `⭐ Дополнительный бонус за Bronze:\n⏩ ¤5.000\n` - break; - case 'silver': - user.money += 15000 - text += `⭐ Дополнительный бонус за Silver:\n⏩ ¤15.000\n` - break; - case 'gold': - user.money += 30000 - text += `⭐ Дополнительный бонус за Gold:\n⏩ ¤30.000\n` - break; - } - user.money += money; - world.balance -= money - if (user.business.id == 0){ - await user.save(); - await world.save(); - return ctx.reply(` - ⭐ Из ежечасного бонуса Вам выпало: -${text} - `) - } - let business = await BusinessModel.findOne({ - where: { - owner: user.business.id - } - }) - if(business != null){ - let mats = rand(3, 10) - switch(user.status){ - case 'bronze': - business.materials += 5 - text += `⭐ Дополнительный бонус за Bronze:\n⏩ 5 материалов\n` - break; - case 'silver': - business.materials += 10 - text += `⭐ Дополнительный бонус за Silver:\n⏩ 10 материалов\n` - break; - case 'gold': - business.materials += 20 - text += `⭐ Дополнительный бонус за Gold:\n⏩ 20 материалов\n` - break; - } - text += `⏩ ${mats} материалов в организацию\n` - business.materials += mats - business.save() - } - await user.save(); - await world.save(); - return ctx.reply(` - ⭐ Из ежечасного бонуса Вам выпало: -${text} - `) -}) - -bot.command('pay', async (ctx) => { - ctx.args = ctx.update.message.text.split(' ') - if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`/pay [Никнейм] [Сумма]`) - if (!Number(ctx.args[2])) return ctx.reply(`❕ Сумма должна быть числовая.`) - let sender = await UserModel.findByPk(ctx.from.id); - let receiver = await UserModel.findOne({ - where: { - username: ctx.args[1] - } - }); - let world = await WorldModel.findByPk(1) - let fee = Number(Math.trunc(ctx.args[2] / 100 * world.transactionfee)) - if (ctx.args[2] == 0 || ctx.args[2] < 100) return ctx.reply(`❕ Минимальная сумма перевода ¤100.`) - if (sender.money < ctx.args[2]) return ctx.reply(`❕ Недостаточно средств!`) - if (sender.money < Number(ctx.args[2]) + fee) return ctx.reply(`❕ Недостаточно средств для перевода с комиссией!`) - sender.money -= Number(ctx.args[2]) - sender.money -= Number(fee) - world.balance += Number(fee) - await sender.save(); - await world.save(); - receiver.money += Number(ctx.args[2]) - await receiver.save(); - let pmToReceiver = `🔽 Входящий перевод.\n\n🔼 Отправитель: ${sender.username}\n🆔 Отправителя: ${sender.telegram_id}\n🔢 Сумма: ¤${ctx.args[2]}\n🆕 Ваш баланс: ¤${receiver.money} - ` - bot.telegram.sendMessage(receiver.telegram_id, pmToReceiver) - return ctx.reply(`🔼 Исходящий перевод.\n\n🔽 Получатель: ${receiver.username}\n🆔 Получателя: ${receiver.telegram_id}\n🔢 Сумма: ¤${ctx.args[2]}\nℹ️ Комиссия: ¤${fee}\n🆕 Ваш баланс: ¤${sender.money} - `) -}) - -bot.hears('Мир', async (ctx) => { - let world = await WorldModel.findByPk(1) - return ctx.reply(`🔰 Баланс мира: ¤${spaces(world.balance)}\nℹ️ Стоимость материалов: ¤${spaces(world.matPrice)} - `) -}) - -bot.hears('📞 Пригласить', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id); - return ctx.reply(` - ℹ️ Для приглашения друга по реферальной системе, отправьте ему ссылку-приглашение -Как только он перейдет по ней и начнет игру, Вы получите ¤25.000. - -Ваша ссылка: https://t.me/CampFireGameBot?start=${user.telegram_id} - `) -}) - -bot.hears('📢 Вакансии', async (ctx) => { - return await ctx.reply('Список работы', Markup - .inlineKeyboard([ - [{ - text: `Дворник [1 уровень]`, - callback_data: 'job_1' - }, { - text: `Промоутер [1 уровень]`, - callback_data: 'job_2' - }], [{ - text: `Официант [2 уровень]`, - callback_data: 'job_3' - }, { - text: `Бармен [3 уровень]`, - callback_data: 'job_4' - }], [{ - text: `Кассир [4 уровень] `, - callback_data: 'job_5' - }, { - text: `ПВЗ Дикие Ягоды [4 уровень]`, - callback_data: 'job_6' - }], [{ - text: `Слесарь [5 уровень]`, - callback_data: 'job_7' - }], [{ - text: `💤 Уволиться`, - callback_data: 'job_leave' - }] - ]) - .resize() - ) -}) - -bot.action(/job_(1|2|3|4|5|6|7|leave)/, async (ctx) => { - let data = ctx.update.callback_query.data; - let user = await UserModel.findByPk(ctx.from.id); - let job = null - switch(data){ - case `job_1`: - job = await JobModel.findByPk(1); - if (user.level < job.level) { - return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) - } - if (user.job == 0) { - user.job = 1 - user.save() - return await ctx.reply(`ℹ️ Вы устроились на работу дворником.\nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) - } - return await ctx.reply(`❕ Вы уже устроены на другую работу`) - case `job_2`: - job = await JobModel.findByPk(2); - if (user.level < job.level) { - return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) - } - if (user.job == 0) { - user.job = 2 - user.save() - return await ctx.reply(`ℹ️ Вы устроились на работу промоутером. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) - } - return await ctx.reply(`❕ Вы уже устроены на другую работу`) - case `job_3`: - job = await JobModel.findByPk(3); - if (user.level < job.level) { - return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) - } - if (user.job == 0) { - user.job = 3 - user.save() - return await ctx.reply(`ℹ️ Вы устроились на работу официантом. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) - } - return await ctx.reply(`❕ Вы уже устроены на другую работу`) - case `job_4`: - job = await JobModel.findByPk(4); - if (user.level < job.level) { - return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) - } - if (user.job == 0) { - user.job = 4 - user.save() - return await ctx.reply(`ℹ️ Вы устроились на работу барменом. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) - } - return await ctx.reply(`❕ Вы уже устроены на другую работу`) - case `job_5`: - job = await JobModel.findByPk(5); - if (user.level < job.level) { - return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) - } - if (user.job == 0) { - user.job = 5 - user.save() - return await ctx.reply(`❕ Вы устроились на работу кассиром. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) - } - return await ctx.reply(`ℹ️ Вы уже устроены на другую работу`) - case `job_6`: - job = await JobModel.findByPk(6); - if (user.level < job.level) { - return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) - } - if (user.job == 0) { - user.job = 6 - user.save() - return await ctx.reply(`ℹ️ Вы устроились на работу в ПВЗ Дикие Ягоды. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) - } - return await ctx.reply(`❕ Вы уже устроены на другую работу`) - case `job_7`: - job = await JobModel.findByPk(7); - if (user.level < job.level) { - return await ctx.reply(`❕ У вас не хватает уровня для этой работы.`) - } - if (user.job == 0) { - user.job = 7 - user.save() - return await ctx.reply(`ℹ️ Вы устроились на работу слесарем. \nВаш оклад: ¤${job.salary}\nПриступайте к работе командой "Работать"`) - } - return await ctx.reply(`❕ Вы уже устроены на другую работу`) - case `job_leave`: - if (user.job != 0) { - user.job = 0 - user.save() - return await ctx.reply(`ℹ️ Теперь вы безработный.`) - } - return await ctx.reply(`❕ Вы итак безработный.`) - } -}) - -bot.hears('🏯 Казино', async (ctx) => { - return await ctx.reply('🏯 Добро пожаловать в казино "杜明"\n', Markup - .keyboard([ - ['🎰 Слоты'], - ['▶️ Меню'] - ]) - .resize() - ) -}) - -bot.hears('🗄️ Работать', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id); - let job = await JobModel.findByPk(user.job); - let world = await WorldModel.findByPk(1) - let timer = user.jobtime - let cooldown = setCooldown(user, 3600, timer) - if (user.jobtime > cooldown.currentTime) return ctx.reply(`📛 Работать можно будет через ${cooldown.timeLeftInMinutes} минут(у/ы)`); - if (user.job == 0) { - return await ctx.reply(`📛 Вы безработный.`) - } - user.jobtime = Number(cooldown.endTime) - let jobExp = job.exp; - user.jobcheck++ - switch (user.job) { - case 1: - if (user.jobcheck >= 4) { - let paydayfee = job.salary / 100 * world.transactionfee - let payday = job.salary - paydayfee - world.balance -= payday - user.money += payday - giveExp(user, jobExp) - user.jobcheck = 0 - user.save() - world.save() - return ctx.reply(`👔 Вы отработали смену дворника. \n🧾 Расчетный лист: \n⏳ Отработано часов: 4/4 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday}`) - } else { - user.save() - return ctx.reply(`👔 Вы подмели дворы. \n⏳ Отработано часов: ${user.jobcheck}/4`) - } - break; - case 2: - if (user.jobcheck >= 2) { - let paydayfee = job.salary / 100 * world.transactionfee - let payday = job.salary - paydayfee - world.balance -= payday - user.money += payday - giveExp(user, jobExp) - user.jobcheck = 0 - user.save() - world.save() - return ctx.reply(`👔 Вы отработали смену промоутера. \n🧾 Расчетный лист: \n⏳ Отработано часов: 2/2 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday}`) - } else { - user.save() - return ctx.reply(`👔 Вы раздавали листовки целый час. \n⏳ Отработано часов: ${user.jobcheck}/2`) - } - break; - case 3: - if (user.jobcheck >= 4) { - let paydayfee = job.salary / 100 * world.transactionfee - let payday = job.salary - paydayfee - world.balance -= payday - let tips = [50, 100, 200, 500, 1000].random() - user.money += tips - user.money += payday - giveExp(user, jobExp) - user.jobcheck = 0 - user.save() - world.save() - return ctx.reply(`👔 Вы отработали смену официанта. \n🧾 Расчетный лист: \n⏳ Отработано часов: 4/4 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday} \n💰 Получено чаевых: ¤${tips}`) - } else { - let tips = [50, 100, 200, 500, 1000].random() - user.money += tips - user.save() - return ctx.reply(`👔 Вы целый час бегали и отрабатывали заказы. \n🧾 Получено чаевых: ¤${tips} \n⏳ Отработано часов: ${user.jobcheck}/4`) - } - break; - case 4: - if (user.jobcheck >= 5) { - let paydayfee = job.salary / 100 * world.transactionfee - let payday = job.salary - paydayfee - world.balance -= payday - let tips = [50, 100, 200, 300, 500, 1000, 2000].random() - world.balance -= tips - user.money += tips - user.money += payday - giveExp(user, jobExp) - user.jobcheck = 0 - user.save() - world.save() - return ctx.reply(`👔 Вы отработали смену бармена. \n🧾 Расчетный лист: \n⏳ Отработано часов: 5/5 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday} \n💰 Получено чаевых: ¤${tips}`) - } else { - let tips = [50, 100, 200, 300, 500, 1000, 2000].random() - world.balance -= tips - user.money += tips - user.save() - world.save() - return ctx.reply(`👔 Вы целый час стояли за стойкой и разливали пойло. \n🧾 Получено чаевых: ¤${tips} \n⏳ Отработано часов: ${user.jobcheck}/5`) - } - break; - case 5: - if (user.jobcheck >= 5) { - let paydayfee = job.salary / 100 * world.transactionfee - let payday = job.salary - paydayfee - world.balance -= payday - user.money += payday - giveExp(user, jobExp) - user.jobcheck = 0 - user.save() - world.save() - return ctx.reply(`👔 Вы отработали смену кассира. \n🧾 Расчетный лист: \n⏳ Отработано часов: 5/5 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday}`) - } else { - user.save() - return ctx.reply(`👔 Вы целый час обслуживали покупателей и кричали: "Гаааляяя, отмена!". \n⏳ Отработано часов: ${user.jobcheck}/5`) - } - break; - case 6: - if (user.jobcheck >= 6) { - let paydayfee = job.salary / 100 * world.transactionfee - let payday = job.salary - paydayfee - let stealed = [{ - name: "Помада", - price: 200 - }, { - name: "Бюстгалтер", - price: 1300 - }, { - name: "Прокладки", - price: 250 - }, { - name: "Перцовый балончик", - price: 600 - }, { - name: "Гитара", - price: 6500 - }, { - name: "Комбик", - price: 9000 - }, { - name: "Кроссовки", - price: 2000 - }, { - name: "Шампунь", - price: 180 - }, { - name: "Смартфон Texno", - price: 6999 - }, { - name: "TWS Гарнитура", - price: 2800 - }, { - name: "Геймпад GameStation 5", - price: 1400 - }, { - name: "Дилдо", - price: 600 - }, { - name: "Вагиноимитатор", - price: 600 - }].random() - world.balance -= payday - world.balance -= Number(stealed.price) - user.money += payday - user.money += Number(stealed.price) - giveExp(user, jobExp) - user.jobcheck = 0 - user.save() - world.save() - return ctx.reply(`👔 Вы отработали смену в Диких Ягодах. \n🧾 Расчетный лист: \n⏳ Отработано часов: 6/6 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday} \n💰 Вы украли и продали со склада: ${stealed.name} (¤${stealed.price})`) - } else { - user.save() - return ctx.reply(`👔 Вы целый час выдавали заказы в Диких Ягодах. \n⏳ Отработано часов: ${user.jobcheck}/6`) - } - break; - case 7: - if (user.jobcheck >= 6) { - let paydayfee = job.salary / 100 * world.transactionfee - let payday = job.salary - paydayfee - world.balance -= payday - user.money += payday - giveExp(user, jobExp) - user.jobcheck = 0 - user.save() - world.save() - return ctx.reply(`👔 Вы отработали смену слесарем. \n🧾 Расчетный лист: \n⏳ Отработано часов: 6/6 \n💸 Оклад: ¤${job.salary} \nℹ️ Подоходный налог: ${world.transactionfee}% \n💹 К выплате: ¤${payday}`) - } else { - user.save() - return ctx.reply(`👔 Вы целый час работали на заводе, вы молодец! \n⏳ Отработано часов: ${user.jobcheck}/6`) - } - break; - } -}) - -bot.hears('Топ', async (ctx) => { - let topPlayer = await UserModel.findAll({ - attributes: ['username', [sequelize.fn('sum', sequelize.col('money')), 'money'], 'status'], - group: ['username', 'status'], - where: { - telegram_id: { - [Op.ne]: 275416286 - } - }, - order: [ - [sequelize.literal('money'), 'DESC'] - ], - limit: 10 - }) - let text = `🏆 Топ 10 игроков по балансу.\n\n` - for(i=0; i { - let user = await UserModel.findByPk(ctx.from.id); - return await ctx.reply(`Выберите тип`, Markup - .inlineKeyboard([ - [ - {text: 'Жилье', callback_data: `shop_house`}, - {text: 'Телефоны', callback_data: `shop_phone`}, - {text: 'Автосалон', callback_data: `shop_car`} - ] - ]) - .resize()) -}) - -bot.action('shopmenu', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id); - return await ctx.editMessageText(`Выберите тип`, Markup - .inlineKeyboard([ - [ - {text: 'Жилье', callback_data: `shop_house`}, - {text: 'Телефоны', callback_data: `shop_phone`}, - {text: 'Автосалон', callback_data: `shop_car`} - ] - ]) - .resize()) -}) - -bot.action(/shop_(house|phone|car)/, async (ctx) => { - let data = ctx.update.callback_query.data; - let prodArray = [] - let text = `Доступно к покупке:\n` - switch(data){ - case `shop_house`: - for (i in houses) { - prodArray.push({text: i, callback_data: `{"action": "buy", "type": "house", "value": "${i}"}`}) - text += i + `. ${houses[i].name} (¤${houses[i].price})\n` - } - break; - case `shop_phone`: - for (i in phones) { - prodArray.push({text: i, callback_data: `{"action": "buy", "type": "phone", "value": "${i}"}`}) - text += i + `. ${phones[i].name} (¤${phones[i].price})\n` - } - break; - case `shop_car`: - for (i in cars) { - prodArray.push({text: i, callback_data: `{"action": "buy", "type": "car", "value": "${i}"}`}) - text += i + `. ${cars[i].name} (¤${cars[i].price})\n` - } - break; - } - prodArray.push({text: `Назад`, callback_data: `shopmenu`}) - let rows = [] - while (prodArray.length > 0) { - rows.push(prodArray.splice(0, 5)) // разбиваем на подмассивы по 5 кнопок - } - return await ctx.editMessageText(text, Markup - .inlineKeyboard(rows) - .resize()) -}) - -bot.action(/{"action": "buy"*/, async (ctx) => { - let data = ctx.update.callback_query.data; - data = JSON.parse(data) - let user = await UserModel.findByPk(ctx.from.id) - let property = await PropertyModel.findByPk(ctx.from.id); - let world = await WorldModel.findByPk(1) - if (data.type == "house") { - if (user.money < houses[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) - if (property.house.name) return await ctx.reply(`У вас уже есть дом.`) - user.money -= houses[data.value].price - world.balance += houses[data.value].price - property.house = houses[data.value] - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы купили ${houses[data.value].name}`) - } - if (data.type == "car") { - if (user.money < cars[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) - if (property.car.name) return await ctx.reply(`У вас уже есть автомобиль.`) - if (!property.house.name) return await ctx.reply(`Для покупки автомобиля, у Вас должен быть дом.`) - user.money -= cars[data.value].price - world.balance += cars[data.value].price - property.car = cars[data.value] - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы купили ${cars[data.value].name}`) - } - if (data.type == "phone") { - if (user.money < phones[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) - if (property.mobile.name) return await ctx.reply(`У вас уже есть телефон.`) - user.money -= phones[data.value].price - world.balance += phones[data.value].price - property.mobile = phones[data.value] - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы купили ${phones[data.value].name}`) - } - if (data.type == "equipment") { - if (user.money < weaponshop[data.value].price) return await ctx.reply(`У вас недостаточно средств!`) - if (data.type == weaponshop[data.value].type) { - if (property.equipment.name) return await ctx.reply(`У вас уже есть экипировка.`) - user.money -= weaponshop[data.value].price - world.balance += weaponshop[data.value].price - property.equipment = weaponshop[data.value] - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы купили ${weaponshop[data.value].name}`) - } - if (property.weapon.name) return await ctx.reply(`У вас уже есть оружие.`) - user.money -= weaponshop[data.value].price - world.balance += weaponshop[data.value].price - property.weapon = weaponshop[data.value] - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы купили ${weaponshop[data.value].name}`) - } -}) - -bot.hears('Поставщик', async (ctx) => { - let text = `[Hatkeis Gunsmith](https://telegra.ph/Hatkeis-Gunsmith-09-27)` - let shop = `\n Вы подходите к зданию с вывеской "Ништяки Хаткейса".\n Вот ассортимент на сегодня\n` - for (i = 0; i < 10; i++) { - shop += `${i}. ${weaponshop[i].name} (¤${spaces(weaponshop[i].price)})\n` - } - weaponShopUpdate() - return await ctx.replyWithMarkdownV2(text + escape(shop), {disable_web_page_preview: true}) -}) - -bot.command('sell', async (ctx) => { - ctx.args = ctx.update.message.text.split(' ') - let user = await UserModel.findByPk(ctx.from.id) - let property = await PropertyModel.findByPk(ctx.from.id); - let world = await WorldModel.findByPk(1) - if (!ctx.args[1]) return ctx.reply(`Не указан аргумент.`) - if (ctx.args[1] == "house") { - if (!property.house.name) return await ctx.reply(`У вас нет дома.`) - let name = property.house.name - user.money += Math.round(property.house.price/2) - world.balance -= Math.round(property.house.price/2) - property.house = 0 - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы продали ${name}`) - } - if (ctx.args[1] == "car") { - if (!property.car.name) return await ctx.reply(`У вас нет автомобиля.`) - let name = property.car.name - user.money += Math.round(property.car.price/2) - world.balance -= Math.round(property.car.price/2) - property.car = 0 - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы продали ${name}`) - } - if (ctx.args[1] == "phone") { - if (!property.mobile.name) return await ctx.reply(`У вас нет телефона.`) - let name = property.mobile.name - user.money += Math.round(property.mobile.price/2) - world.balance -= Math.round(property.mobile.price/2) - property.mobile = 0 - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы продали ${name}`) - } - if (ctx.args[1] == "equipment") { - if (!property.equipment.name) return await ctx.reply(`У вас нет экипировки.`) - let name = property.equipment.name - user.money += Math.round(property.equipment.price/2) - world.balance -= Math.round(property.equipment.price/2) - property.equipment = 0 - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы продали ${name}`) - } - if (ctx.args[1] == "weapon") { - if (!property.weapon.name) return await ctx.reply(`У вас нет оружия.`) - let name = property.weapon.name - user.money += Math.round(property.weapon.price/2) - world.balance -= Math.round(property.weapon.price/2) - property.weapon = 0 - await user.save() - await world.save() - await property.save() - return await ctx.reply(`Вы продали ${name}`) - } -}) - -bot.hears('🌐 Организация', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) - let business = await BusinessModel.findOne({ - where: { - owner: ctx.from.id.toString() - } - }) - if(business === null){ - business = await BusinessModel.findOne({ - where: { - owner: user.business.id - } - }) - return await ctx.replyWithMarkdownV2(`🏭 Организация\n_${business.name}_\n💹 Баланс: ¤${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n\nВаши отработки: ${user.business.checks}`, Markup.inlineKeyboard([ - [{ - text: `📶 Отработка`, - callback_data: "workoff" - }, { - text: `⬅️ Покинуть`, - callback_data: "покинуть" - }] - ]) - .oneTime() - .resize()) - } - if (business.owner == ctx.from.id){ - return await ctx.replyWithMarkdownV2(`🏭 Ваша организация\n_${business.name}_\n💹 Баланс: ¤${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n🔨 Отработок: ${business.checks}\n\nВаши отработки: ${user.business.checks}`, Markup.inlineKeyboard([ - [{ - text: `📶 Отработка`, - callback_data: "workoff" - }, { - text: `💸 Payday`, - callback_data: "payday" - }] - ]) - .oneTime() - .resize()) - } -}) - -bot.action('workoff', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - let business = await BusinessModel.findOne({ - where: { - owner: user.business.id.toString() - } - }) - if (user.business == null) return await ctx.reply(`Вы не работаете в организации.`) - let timer = user.worktime - let cooldown = setCooldown(user, 3600, timer) - if (user.worktime > cooldown.currentTime) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `📛 Работа в организации будет доступна через ${cooldown.timeLeftInMinutes} минут(у/ы)`, {show_alert: true}); - if (business.materials < 10) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `📛 В организации недостаточно материалов для отработки.`); - user.worktime = cooldown.endTime - user.business = { - id: user.business.id, - checks: user.business.checks + 1, - percent: user.business.percent - } - business.materials -= 10 - business.checks += 1 - await user.save() - await business.save() - if (business.owner == ctx.from.id){ - return await ctx.editMessageText(`🏭 Ваша организация\n_${business.name}_\n💹 Баланс: ¤${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials} \n👥 Рабочих: ${business.users.length}\n🔨 Отработок: ${business.checks}\n\nВаши отработки: ${user.business.checks}`, - { - reply_markup: { - inline_keyboard: [ - [{ - text: `📶 Отработка`, - callback_data: "workoff" - }, { - text: `💸 Payday`, - callback_data: "payday" - }] - ]}, - parse_mode: `MarkdownV2` - } - ) - }else{ - return await ctx.editMessageText(`🏭 Организация\n_${business.name}_\n💹 Баланс: ¤${escape(spaces(business.balance))}\n🧰 Сырье: ${business.materials}\n👥 Рабочих: ${business.users.length}\n\nВаши отработки: ${user.business.checks}`, - { - reply_markup: { - inline_keyboard: [ - [{ - text: `📶 Отработка`, - callback_data: "workoff" - }, { - text: `⬅️ Покинуть`, - callback_data: "покинуть" - }] - ]}, - parse_mode: `MarkdownV2` - } - ) - } -}) - -bot.action('покинуть', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) - let business = await BusinessModel.findOne({ - where: { - owner: ctx.from.id.toString() - } - }) - if(business === null){ - business = await BusinessModel.findOne({ - where: { - owner: user.business.id - } - }) - await ctx.reply(`Подтвердите в личных сообщениях.`) - return await bot.telegram.sendMessage(ctx.from.id, `🏭 Вы действительно хотите покинуть ${business.name}`, Markup.inlineKeyboard([ - [{ - text: `Да`, - callback_data: "user_leave_business" - }, { - text: `Нет`, - callback_data: "cancel" - }] - ]) - .oneTime() - .resize() - ) - } - if (business.owner == ctx.from.id){ - return await ctx.reply(`Вы не можете покинуть свою организацию.`) - } -}) - -bot.action('cancel', async (ctx) => { - await ctx.deleteMessage() - await bot.telegram.answerCbQuery(ctx.callbackQuery.id, `Отмена.`) -}) - -bot.action('user_leave_business', async (ctx) => { - let data = ctx.update.callback_query.data; - let user = await UserModel.findByPk(ctx.from.id) - if (user.business.id == 0) return await ctx.reply(`Вы не состоите в организации.`) - let business = await BusinessModel.findOne({ - where: { - owner: user.business.id - } - }) - user.business = { - id: 0, - checks: 0, - percent: 0 - } - business.users = business.users.filter(value => value != ctx.from.id); - business.save() - user.save() - return await bot.telegram.sendMessage(ctx.from.id, `🏭 Вы покинули ${business.name}`) -}) - -bot.action('payday', async (ctx) => { - let user = null - let business = await BusinessModel.findOne({ - where: { - owner: ctx.from.id.toString() - } - }) - let world = await WorldModel.findByPk(1) - if (business === null) return await ctx.reply(`У вас нет организации.`) - if (business.checks < 12) return await ctx.reply(`Недостаточно отработок для формирования выплаты.`) - let percentSum = 0 - let text = `` - let percentErrorText = `` - let profit = 0 - let piece = 0 - let moneyList = rand(1000, 3000) - moneyList = moneyList*business.users.length - for (i = 0; i < business.users.length; i++) { // Summary percent - user = await UserModel.findByPk(business.users[i]) - percentSum += Number(user.business.percent) - percentErrorText += `ℹ️ ${user.username} ${user.business.percent}% [/percent ${user.username} [проценты]]\n` - } - if (percentSum > 100) return await ctx.reply(`⚠️ Общий процент всех сотрудников превышает 100%\n ➕ Остаток процентов перенесется в баланс организации.\n\n${percentErrorText}\n`) - for (x = 0; x < business.users.length; x++) { // Общая внесенная сумма всеми участниками - user = await UserModel.findByPk(business.users[x]) - profit += user.business.checks * moneyList * user.level - text += `ℹ️ ${user.username} отработал ${user.business.checks} раз.\n` - user.business = { - id: user.business.id, - checks: 0, - percent: user.business.percent - } - user.save() - } - text += ` 💹 Наработка за текущий период: ${profit}\n` - let profitCheck = profit - for (n = 0; n < business.users.length; n++) { // Процент выплаты участникам - user = await UserModel.findByPk(business.users[n]) - piece = Math.round(profit / 100 * user.business.percent) - profitCheck -= piece - user.money += piece - text += `➕ ${user.username} получает ¤${piece}\n` - await bot.telegram.sendMessage(user.telegram_id, `ℹ️ Директор организации сформировал выплаты.\n➕ На ваш баланс поступило: ${spaces(piece)}`) - giveExp(user, business.checks) - user.save() - } - if (profitCheck > 0) { - business.balance += profitCheck - text += `➕ На баланс бизнеса поступило ¤${profitCheck}` - } - business.checks = 0 - business.save() - console.log(`Payday: ${business.name}\n${text}`) - return await ctx.reply(text) -}) - -bot.command('orgmessage', async (ctx) => { - if (!ctx.args[1]) return ctx.reply(`Не указан аргумент.`) - let business = await BusinessModel.findOne({ - where: { - owner: ctx.from.id.toString() - } - }) - if (business === null) return await ctx.reply(`У вас нет организации.`) - for (i = 0; i < business.users.length; i++) { - user = await UserModel.findByPk(business.users[i]) - await bot.telegram.sendMessage(user.telegram_id, `Директор организации сообщает:\n ${ctx.payload}`) - } - console.log(`Директор организации сообщает:\n ${ctx.payload}`) - return await ctx.reply(`Сообщение отправлено.`) -}) - -bot.command('materials', async (ctx) => { - ctx.args = ctx.update.message.text.split(' ') - let user = await UserModel.findByPk(ctx.from.id) - if (user.business.id == 0) return await ctx.reply(`🚫 Вы не владеете организацией.`) - let world = await WorldModel.findByPk(1) - let business = await BusinessModel.findOne({ - where: { - owner: ctx.from.id.toString() - } - }) - if (business === null) return await ctx.reply(`🚫 У вас нет организации.`) - if (!ctx.args[1]) return ctx.reply(`🚫 Не указан аргумент.`) - if (!Number(ctx.args[1])) return ctx.reply(`ℹ️ Количество должно быть числом.`) - if (ctx.args[1] < 1) return ctx.reply(`ℹ️ Минимальное количество для покупки - 1`) - if (ctx.args[1]*world.matPrice > business.balance) return ctx.reply(`🚫 Недостаточно средств на балансе организации.`) - if (business.materials >= 700) return ctx.reply(`🚫 Склады полны.`) - if (business.materials + Number(ctx.args[1]) > 700) return ctx.reply(`🚫 Нет столько места на складах.\n Можно закупить еще ${700 - business.materials}`) - let count = Number(ctx.args[1]) - business.balance -= world.matPrice*count - business.materials += count - business.save() - return await ctx.reply(`➕ Закуплено ${ctx.args[1]} материалов для организации на сумму ¤${world.matPrice*count}`) -}) - -bot.command('percent', async (ctx) => { - ctx.args = ctx.update.message.text.split(' ') - let user = await UserModel.findByPk(ctx.from.id) - if (user.business.id == 0) return await ctx.reply(`Вы не владеете организацией.`) - let business = await BusinessModel.findOne({ - where: { - owner: ctx.from.id.toString() - } - }) - if (business === null) return await ctx.reply(`У вас нет организации.`) - if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`Не указан аргумент.`) - if (!Number(ctx.args[2])) return ctx.reply(`Процент должен быть числом от 1 до 100.`) - if (ctx.args[2] < 1 || ctx.args[2] > 100) return ctx.reply(`Минимальный процент 1 | Максимальный процент 100.`) - ctx.args[1] = ctx.args[1] - console.log(ctx.args) - let change = await UserModel.findOne({ - where: { - username: ctx.args[1] - } - }) - if (change === null) return await ctx.reply(`Нет такого игрока.`) - change.business = { - id: change.business.id, - checks: change.business.checks, - percent: ctx.args[2] - } - change.save() - return await ctx.reply(`Участнику ${change.username} установлен процент ${ctx.args[2]}`) -}) - -bot.command('business', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - if (user.business.id != 0){ - let business = await BusinessModel.findOne({ - where: { - owner: ctx.from.id.toString() - } - }) - } - let business = null - let world = await WorldModel.findByPk(1) - ctx.args = ctx.update.message.text.split(' ') - if (business != null) return await ctx.reply(`У вас уже есть организация.`) - if (!ctx.args[1]) return ctx.reply(`/business [Название организации]`) - if (user.money < 100000) return await ctx.reply(`Регистрация организации стоит ¤100.000`) - if (user.level < 5) return await ctx.reply(`Регистрация организации доступна с 5 уровня.`) - user.money -= 100000 - world.balance += 100000 - let text = `` - for (i = 1; i < ctx.args.length; i++) { - text += `${ctx.args[i]} ` - } - if (business === null) { - BusinessModel.create({ - name: text, - owner: user.telegram_id, - balance: 50000, - users: [user.telegram_id] - }) - user.business = { - id: user.telegram_id, - checks: 0, - percent: 100 - } - } else {} - user.save() - world.save() - return await ctx.reply(`Организация "${text}" успешно создана!\n Регистрация организации в реестре: ¤50.000 \n Капитал: ¤50.000`) -}) - -bot.command('invite', async (ctx) => { - ctx.args = ctx.update.message.text.split(' ') - if (!ctx.args[1]) return ctx.reply(`/invite [Nick]`) - let user = await UserModel.findByPk(ctx.from.id) - if (user.business.id == 0) return await ctx.reply(`🚫 У вас нет организации в которую можно пригласить игрока.`) - let business = await BusinessModel.findOne({ - where: { - owner: ctx.from.id.toString() - } - }) - if (business.users.length >= 5) return await ctx.reply(`📛 Достигнуто максимальное количество сотрудников в организации.`) - let invited = await UserModel.findOne({ - where: { - username: ctx.args[1] - } - }); - await bot.telegram.sendMessage(invited.telegram_id, '⤵️ Приглашение', Markup - .inlineKeyboard([ - [{ - text: `Принять`, - callback_data: `{"type": "business_invite_accept", "invitor": "${user.telegram_id}"}` - }, { - text: `Отклонить`, - callback_data: `{"type": "business_invite_refuse", "invitor": "${user.telegram_id}"}` - }] - ]).oneTime()) - return await ctx.reply(`Приглашение отправлено.`) -}) - -bot.action(/{"type": "business_invite_(accept|refuse)"*/, async ctx => { - let data = ctx.update.callback_query.data; - data = JSON.parse(data) - let user = await UserModel.findByPk(ctx.update.callback_query.from.id) - if (data.type == 'business_invite_accept') { - if(user.business.id == 0){ - let business = await BusinessModel.findOne({ - where: { - owner: data.invitor - } - }) - user.business = { - id: data.invitor, - checks: 0, - percent: 10 - } - business.users = sequelize.fn('array_append', sequelize.col('users'), ctx.update.callback_query.from.id); - business.save() - user.save() - await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `✔️ Приглашение принято.`, {show_alert: true}) - } - await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `ℹ️ Вы уже в организации.`, {show_alert: true}) - } - if (data.type == 'business_invite_refuse'){ - await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `❌ Приглашение отклонено.`, {show_alert: true}) - } -}) - -bot.command('report', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - ctx.args = ctx.update.message.text.split(' ') - if (!ctx.args[1]) return ctx.reply(`/report [Текст обращения]`) - let uID = shortid.generate() - await ReportModel.create({ - uid: uID, - author: user.telegram_id, - text: ctx.payload, - status: 1 - }) - let report = await ReportModel.findOne({ - where: { - uid: uID - } - }) - await bot.telegram.sendMessage(adminList[0], `Обращение от пользователя ${user.username}\nТекст обращения:\n${ctx.payload}\n\nДля ответа /answer ${report.id} [Ответ]`) - return await ctx.reply(`Обращение #${report.id}[${report.uid}] создано.`) -}) - -bot.hears('🎰 Слоты', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - ctx.args = ctx.update.message.text.split(' ') - await ctx.reply('Комбинации слотов:\n7️⃣7️⃣7️⃣ - x25\n🍋🍋🍋 - x20\n🍇🍇🍇 - x15\n🔤🔤🔤 - x10', Markup - .inlineKeyboard([ - [{ - text: `1000`, - callback_data: `slots1000` - }, { - text: `5000`, - callback_data: `slots5000` - }, { - text: `25000`, - callback_data: `slots25000` - }, { - text: `50000`, - callback_data: `slots50000` - }, { - text: `100000`, - callback_data: `slots100000` - }] - ])) -}) - -bot.action(/slots(1000|5000|25000|50000|100000)/, async (ctx) => { - let data = ctx.update.callback_query.data; - let bet = 1000 - switch(data){ - case `slots1000`: - bet = 1000 - break; - case `slots5000`: - bet = 5000 - break; - case `slots25000`: - bet = 25000 - break; - case `slots50000`: - bet = 50000 - break; - case `slots100000`: - bet = 100000 - break; - } - let user = await UserModel.findByPk(ctx.from.id) - let timer = user.slottime - let cooldown = setCooldown(user, 10, timer) - if (user.slottime > cooldown.currentTime) return ctx.reply(`📛 Слоты будут доступны через пару секунд`); - if (user.money < bet) return ctx.reply(`Недостаточно средств.`) - user.slottime = cooldown.endTime - let world = await WorldModel.findByPk(1) - let result = await ctx.replyWithDice({emoji: `🎰`}) - let slot = slots[result.dice.value] - let win = getSlot(result) - console.log(user.username + `: Win: x` + win) - user.money -= bet - world.balance += bet - if(win > 4){ - user.world -= bet*win - user.money += bet*win - user.save() - world.save() - return setTimeout(() => { - ctx.reply(`➕ Вы выиграли ¤${spaces(bet*win)}`) - }, 1700); - } - if(win > 0 && win <= 4){ - await giveExp(user, win*2) - return setTimeout(() => { - ctx.reply(`➕ Вы выиграли ${win*2} опыта.`) - }, 1700); - } - if(win == 0){ - return setTimeout(() => { - world.save() - user.save() - ctx.reply(`➖ Вы проиграли ¤${spaces(bet)}.`) - }, 1700); - } - -}) - -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', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - ctx.args = ctx.update.message.text.split(' ') - if (!ctx.args[1]) return ctx.reply(`/promocode [Code]`) - let promocode = await PromocodeModel.findOne({ - where: { - code: ctx.args[1] - } - }) - if(promocode === null) return await ctx.reply(`➖ Нет такого кода.`) - if(promocode.users.length-1 >= promocode.activations && promocode.users != null) return await ctx.reply(`⚠️ Промокод уже активировали максимальное количество раз.`) - if(promocode.users.includes(ctx.from.id.toString())) return await ctx.reply(`⚠️ Вы уже активировали этот промокод.`) - console.log(promocode.users) - promocode.users = sequelize.fn('array_append', sequelize.col('users'), ctx.from.id.toString()); - user.money += promocode.money - user.save() - promocode.save() - await bot.telegram.sendMessage(adminList[0], `${user.username} активировал промокод.`) - return await ctx.reply(`✅ Вы активировали промокод.`) -}) - -bot.hears('📦 Контейнеры', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - let containers = [] - let superWin = rarecars.random() - let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - let oneValue = [] - for(i = 0; i < 10; i++){ - oneValue = values.random() - values = values.filter(value => value != oneValue); - containers.push({name: `📦 Контейнер ${i+1}`, value: oneValue}) - } - let keyboardButtons = containers.map(container => { - return {text: container.name, callback_data: `container_${container.value}`} - }) - let rows = [] - while (keyboardButtons.length > 0) { - rows.push(keyboardButtons.splice(0, 2)) // разбиваем на подмассивы по 5 кнопок - } - await ctx.replyWithMarkdownV2('[Sueta Logistic International](https://telegra.ph/OOO-Sueta-Logistic-International-09-27)\nДоступные контейнеры в порту:', - { - reply_markup: { - inline_keyboard: rows - }, - disable_web_page_preview: true - }) -}) - - -bot.action(/container_(1|2|3|4|5|6|7|8|9|10)/, async (ctx) => { - let data = ctx.update.callback_query.data; - let user = await UserModel.findByPk(ctx.from.id) - let property = await PropertyModel.findByPk(ctx.from.id) - if(user.money < 500000) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Открытие контейнера стоит ¤500.000`, {show_alert: true}) - if(property.car.name) return ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас уже есть автомобиль\nПродайте текущий автомобиль: /sell car`, {show_alert: true}) - user.money -= 500000 - let userWin = null - switch(data){ - case `container_7`: - userWin = rarecars.random() - break; - default: - userWin = simplecars.random() - break; - } - property.car = userWin - user.save() - property.save() - ctx.deleteMessage() - return await ctx.sendPhoto(userWin.image, { caption: `В контейнере была: ${userWin.name} стоимостью ¤${spaces(userWin.price)}`}) -}) - -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() -}) -/////////////////////////////////////Admin Commands////////////////////////////////////////////////// - - -bot.command('answer', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - if(user.status != 'admin') return await ctx.reply(`Admin Only.`) - ctx.args = ctx.update.message.text.split(' ') - if (!ctx.args[1]) return ctx.reply(`Нужен номер обращения`) - let report = await ReportModel.findByPk(ctx.args[1]) - if (report === null) return await ctx.reply(`Нет обращения с таким ID.`) - if (report.status == 0) return await ctx.reply(`Данное обращение уже закрыто.`) - let answer = ctx.args - answer.shift() - answer.shift() - answer = answer.join(' ') - await bot.telegram.sendMessage(report.author, `Ответ на обращение #${report.id}[${report.uid}]\n\n` + answer) - report.status = 0 - report.save() - return await ctx.reply(`Ответ отправлен, обращение закрыто!`) -}) - -bot.command('fastblock', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - if(!ctx.message.reply_to_message) return await ctx.reply(`Только на пересланное сообщение.`) - let blocked = ctx.message.reply_to_message.from.id - 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(`Пользователь заблокирован.`) -}) - -bot.command('createpromocode', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - if(user.status != 'admin') return await ctx.reply(`Admin Only.`) - ctx.args = ctx.update.message.text.split(' ') - if (!ctx.args[1] || !ctx.args[2] || !ctx.args[3]) return ctx.reply(`/createpromo [activations] [money] [code]`) - let promocode = await PromocodeModel.findOne({ - where: { - code: ctx.args[3] - } - }) - if(promocode === null){ - await PromocodeModel.create({ - code: ctx.args[3], - activations: ctx.args[1], - money: ctx.args[2] - }) - let voucherImage = await generateVoucher(ctx.args[3], ctx.args[1], ctx.args[2]) - return await ctx.sendPhoto({source: voucherImage, caption: `Создан промокод ${ctx.args[3]}` }) -} -}) - -bot.command('genpromo', async (ctx) => { - let user = await UserModel.findByPk(ctx.from.id) - if(user.status != 'admin') return await ctx.reply(`Admin Only.`) - ctx.args = ctx.update.message.text.split(' ') - if (!ctx.args[1] || !ctx.args[2]) return ctx.reply(`/genpromo [activations] [money]`) - let code = voucher_codes.generate({ - length: 6, - count: 1, - prefix: "CMP-", - postfix: "-FIRE", - charset: voucher_codes.charset("alphanumeric") - }); - let promocode = await PromocodeModel.findOne({ - where: { - code: code[0] - } - }) - if(promocode === null){ - await PromocodeModel.create({ - code: code[0], - activations: ctx.args[1], - money: ctx.args[2] - }) - let voucherImage = await generateVoucher(code, ctx.args[1], ctx.args[2]) - return await ctx.sendPhoto({source: voucherImage, caption: `Создан промокод ${code[0]}` }) -} -}) - -///////////////////////////////////////Functions////////////////////////////////////////////////////// - -function rand(min, max) { - return Math.round(Math.random() * (max - min)) + min -} -var parserInt = (str) => parseInt(str.replace(/k|к/ig, "000")); - -function spaces(string) { - if (typeof string !== "string") string = string.toString(); - return string.split("").reverse().join("").match(/[0-9]{1,3}/g).join(".").split("").reverse().join(""); -}; -function spacesWithMarkdown(string) { - if (typeof string !== "string") string = string.toString(); - return string.split("").reverse().join("").match(/[0-9]{1,3}/g).join(".\\").split("").reverse().join(""); -}; -function escape(text) { - text = text - .replace(/\_/g, '\\_') - .replace(/\*/g, '\\*') - .replace(/\[/g, '\\[') - .replace(/\]/g, '\\]') - .replace(/\(/g, '\\(') - .replace(/\)/g, '\\)') - .replace(/\~/g, '\\~') - .replace(/\`/g, '\\`') - .replace(/\>/g, '\\>') - .replace(/\#/g, '\\#') - .replace(/\+/g, '\\+') - .replace(/\-/g, '\\-') - .replace(/\=/g, '\\=') - .replace(/\|/g, '\\|') - .replace(/\{/g, '\\{') - .replace(/\}/g, '\\}') - .replace(/\./g, '\\.') - .replace(/\!/g, '\\!'); - return text -}; -Array.prototype.random = function() { - return this[Math.floor(this.length * Math.random())]; -} - -function getCurrentTime() { - const now = new Date(); - const year = now.getFullYear(); - const month = now.getMonth() < 9 ? `0${now.getMonth() + 1}` : now.getMonth() + 1; - const day = now.getDate() < 10 ? `0${now.getDate()}` : now.getDate(); - const hours = now.getHours() < 10 ? `0${now.getHours()}` : now.getHours(); - const minutes = now.getMinutes() < 10 ? `0${now.getMinutes()}` : now.getMinutes(); - const seconds = now.getSeconds() < 10 ? `0${now.getSeconds()}` : now.getSeconds(); - return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`; -} - -function getSlot(result) { - switch(result.dice.value){ - case 1: - return 10 - case 22: - return 15 - case 43: - return 20 - case 64: - return 25 - case 17: case 33: case 49: - return 1 - case 6: case 38: case 54: - return 2 - case 11: case 27: case 59: - return 3 - case 16: case 32: case 48: - return 4 - default: - return 0 -}} - -function setCooldown(user, seconds, type) { - let cooldown = {} - cooldown.currentTime = Math.trunc(Date.now() / 1000) - - switch(user.status){ - case `user`: - cooldown.endTime = Math.trunc(Date.now() / 1000 + seconds) - break; - case `bronze`: - cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*85)) - break; - case `silver`: - cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*75)) - break; - case `gold`: - cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*50)) - break; - case `admin`: - cooldown.endTime = Math.trunc(Date.now() / 1000) - break; - } - cooldown.timeLeft = cooldown.endTime - cooldown.currentTime - cooldown.timeLeftInMinutes = Math.ceil((type - cooldown.currentTime) / 60) - return cooldown -} - -async function giveExp(user, experience) { - user.exp += experience - for(i in expToUp){ - if (user.exp >= expToUp[user.level]) { - user.exp -= expToUp[user.level] - user.level += 1 - user.save() - await bot.telegram.sendMessage(user.telegram_id, `⤴️ Ваш уровень повысился до ${user.level}!`)} - } - user.save() -} - -function weaponShopUpdate() { - let weaponId = [] - let equipId = [] - let drop = 1 - let counter = 5 - for (i = 0; i < 5; i++) { - drop = weaponId.push(rand(1, 10)) - } - for (i = 0; i < 5; i++) { - drop = equipId.push(rand(1, 10)) - } - for (i = 0; i < 5; i++) { - weaponshop[i] = weapons[weaponId[i]] - } - for (i = 0; i < 5; i++) { - weaponshop[counter] = equipment[equipId[i]] - counter++ - } - fs.writeFileSync('json/weaponshop.json', JSON.stringify(weaponshop, null, "\t")) -} - -async function matPriceUpdate() { - let world = await WorldModel.findByPk(1) - let price = rand(35, 170) - world.matPrice = price - world.save() -} - -setTimeout(() => { - generatePromo() -}, 360000*3); - -setInterval(() => { - var today = new Date(); - let hours = today.getHours(); - if (hours == "0" || hours == "12") { - weaponShopUpdate() - matPriceUpdate() - } -}, 360000); - -async function generatePromo() { - let activs = rand(1, 3) - let give = rand(1000, 10000) - let code = voucher_codes.generate({ - length: 6, - count: 1, - prefix: "CMP-", - postfix: "-FIRE", - charset: voucher_codes.charset("alphanumeric") - }); - let promocode = await PromocodeModel.findOne({ - where: { - code: code[0] - } - }) - if(promocode === null){ - await PromocodeModel.create({ - code: code[0], - activations: activs, - money: give - }) - let voucherImage = await generateVoucher(code[0], activs, give) - return await bot.telegram.sendPhoto(mainChat, {source: voucherImage}) -} -} - -async function generateVoucher(code, activations, money) { - // загружаем изображение фона - const background = await loadImage('./media/imageDefault3.png'); - - // создаем новый canvas - const canvas = createCanvas(background.width, background.height); - const ctx = canvas.getContext('2d'); - - // рисуем фоновое изображение - ctx.drawImage(background, 0, 0); - - // выводим текст на картинку - ctx.font = 'bold 30px Srbija Sans'; - ctx.fillStyle = '#232323'; - ctx.textAlign = 'center'; - ctx.fillText(`${code}`, canvas.width/2, canvas.height/1.90); - - // сохраняем картинку в файл - const out = fs.createWriteStream('./media/image.png'); - const stream = canvas.createPNGStream(); - stream.pipe(out); - - // возвращаем путь к сгенерированной картинке - return './media/image.png'; - } - -start() - -bot.launch() \ No newline at end of file +require('./bot') \ No newline at end of file diff --git a/json/fastlog.json b/json/fastlog.json new file mode 100644 index 0000000..f550efe --- /dev/null +++ b/json/fastlog.json @@ -0,0 +1,2460 @@ +{ + "update": { + "update_id": 757696514, + "callback_query": { + "id": "7719528038798802037", + "from": { + "id": 1797342681, + "is_bot": false, + "first_name": "Wild", + "last_name": "Developer", + "username": "wild_dev", + "language_code": "ru" + }, + "message": { + "message_id": 23044, + "from": { + "id": 6489664401, + "is_bot": true, + "first_name": "CampFire", + "username": "CampFireGameBot" + }, + "chat": { + "id": 1797342681, + "first_name": "Wild", + "last_name": "Developer", + "username": "wild_dev", + "type": "private" + }, + "date": 1695764308, + "text": "Приглашение", + "reply_markup": { + "inline_keyboard": [ + [ + { + "text": "Принять", + "callback_data": "{type: business_invite_accept, invitor: 275416286}" + }, + { + "text": "Отклонить", + "callback_data": "{type: business_invite_refuse, invitor: 275416286}" + } + ] + ] + } + }, + "chat_instance": "3234091630426335107", + "data": "{type: business_invite_accept, invitor: 275416286}" + } + }, + "telegram": { + "token": "6489664401:AAHTimMFrCzFUXhHGmiMDwWhsAVs6J3rrLs", + "options": { + "apiRoot": "https://api.telegram.org", + "apiMode": "bot", + "webhookReply": true, + "agent": { + "_events": {}, + "_eventsCount": 2, + "defaultPort": 443, + "protocol": "https:", + "options": { + "keepAlive": true, + "keepAliveMsecs": 10000, + "noDelay": true, + "path": null + }, + "requests": {}, + "sockets": {}, + "freeSockets": { + "api.telegram.org:443:::::::::::::::::::::": [ + { + "_tlsOptions": { + "pipe": false, + "secureContext": { + "context": {} + }, + "isServer": false, + "requestCert": true, + "rejectUnauthorized": true + }, + "_secureEstablished": true, + "_securePending": false, + "_newSessionPending": false, + "_controlReleased": true, + "secureConnecting": false, + "_SNICallback": null, + "servername": "api.telegram.org", + "alpnProtocol": false, + "authorized": true, + "authorizationError": null, + "encrypted": true, + "_events": { + "close": [ + null, + null, + null + ] + }, + "_eventsCount": 9, + "connecting": false, + "_hadError": false, + "_parent": null, + "_host": "api.telegram.org", + "_closeAfterHandlingError": false, + "_readableState": { + "objectMode": false, + "highWaterMark": 16384, + "buffer": { + "head": null, + "tail": null, + "length": 0 + }, + "length": 0, + "pipes": [], + "flowing": true, + "ended": false, + "endEmitted": false, + "reading": true, + "constructed": true, + "sync": false, + "needReadable": true, + "emittedReadable": false, + "readableListening": false, + "resumeScheduled": false, + "errorEmitted": false, + "emitClose": false, + "autoDestroy": true, + "destroyed": false, + "errored": null, + "closed": false, + "closeEmitted": false, + "defaultEncoding": "utf8", + "awaitDrainWriters": null, + "multiAwaitDrain": false, + "readingMore": false, + "dataEmitted": true, + "decoder": null, + "encoding": null + }, + "_writableState": { + "objectMode": false, + "highWaterMark": 16384, + "finalCalled": false, + "needDrain": false, + "ending": false, + "ended": false, + "finished": false, + "destroyed": false, + "decodeStrings": false, + "defaultEncoding": "utf8", + "length": 0, + "writing": false, + "corked": 0, + "sync": false, + "bufferProcessing": false, + "writecb": null, + "writelen": 0, + "afterWriteTickInfo": null, + "buffered": [], + "bufferedIndex": 0, + "allBuffers": true, + "allNoop": true, + "pendingcb": 0, + "constructed": true, + "prefinished": false, + "errorEmitted": false, + "emitClose": false, + "autoDestroy": true, + "errored": null, + "closed": false, + "closeEmitted": false + }, + "allowHalfOpen": false, + "_sockname": null, + "_pendingData": null, + "_pendingEncoding": "", + "_server": null, + "ssl": { + "_parent": { + "reading": true, + "onconnection": null + }, + "_secureContext": { + "context": {} + }, + "reading": true + }, + "_requestCert": true, + "_rejectUnauthorized": true, + "parser": null, + "_httpMessage": null, + "timeout": 0 + }, + { + "_tlsOptions": { + "pipe": false, + "secureContext": { + "context": {} + }, + "isServer": false, + "requestCert": true, + "rejectUnauthorized": true + }, + "_secureEstablished": true, + "_securePending": false, + "_newSessionPending": false, + "_controlReleased": true, + "secureConnecting": false, + "_SNICallback": null, + "servername": "api.telegram.org", + "alpnProtocol": false, + "authorized": true, + "authorizationError": null, + "encrypted": true, + "_events": { + "close": [ + null, + null, + null + ] + }, + "_eventsCount": 9, + "connecting": false, + "_hadError": false, + "_parent": null, + "_host": "api.telegram.org", + "_closeAfterHandlingError": false, + "_readableState": { + "objectMode": false, + "highWaterMark": 16384, + "buffer": { + "head": null, + "tail": null, + "length": 0 + }, + "length": 0, + "pipes": [], + "flowing": true, + "ended": false, + "endEmitted": false, + "reading": true, + "constructed": true, + "sync": false, + "needReadable": true, + "emittedReadable": false, + "readableListening": false, + "resumeScheduled": false, + "errorEmitted": false, + "emitClose": false, + "autoDestroy": true, + "destroyed": false, + "errored": null, + "closed": false, + "closeEmitted": false, + "defaultEncoding": "utf8", + "awaitDrainWriters": null, + "multiAwaitDrain": false, + "readingMore": false, + "dataEmitted": true, + "decoder": null, + "encoding": null + }, + "_writableState": { + "objectMode": false, + "highWaterMark": 16384, + "finalCalled": false, + "needDrain": false, + "ending": false, + "ended": false, + "finished": false, + "destroyed": false, + "decodeStrings": false, + "defaultEncoding": "utf8", + "length": 0, + "writing": false, + "corked": 0, + "sync": false, + "bufferProcessing": false, + "writecb": null, + "writelen": 0, + "afterWriteTickInfo": null, + "buffered": [], + "bufferedIndex": 0, + "allBuffers": true, + "allNoop": true, + "pendingcb": 0, + "constructed": true, + "prefinished": false, + "errorEmitted": false, + "emitClose": false, + "autoDestroy": true, + "errored": null, + "closed": false, + "closeEmitted": false + }, + "allowHalfOpen": false, + "_sockname": null, + "_pendingData": null, + "_pendingEncoding": "", + "_server": null, + "ssl": { + "_parent": { + "reading": true, + "onconnection": null + }, + "_secureContext": { + "context": {} + }, + "reading": true + }, + "_requestCert": true, + "_rejectUnauthorized": true, + "parser": null, + "_httpMessage": null, + "timeout": 0 + } + ] + }, + "keepAliveMsecs": 10000, + "keepAlive": true, + "maxSockets": null, + "maxFreeSockets": 256, + "scheduling": "lifo", + "maxTotalSockets": null, + "totalSocketCount": 2, + "maxCachedSessions": 100, + "_sessionCache": { + "map": { + "api.telegram.org:443:::::::::::::::::::::": { + "type": "Buffer", + "data": [ + 48, + 130, + 8, + 51, + 2, + 1, + 1, + 2, + 2, + 3, + 4, + 4, + 2, + 19, + 2, + 4, + 32, + 115, + 64, + 227, + 66, + 58, + 149, + 105, + 85, + 239, + 246, + 207, + 73, + 6, + 113, + 104, + 72, + 91, + 65, + 237, + 145, + 15, + 232, + 0, + 165, + 158, + 207, + 69, + 121, + 37, + 3, + 86, + 23, + 4, + 48, + 116, + 131, + 217, + 130, + 92, + 49, + 241, + 229, + 129, + 139, + 122, + 11, + 222, + 185, + 28, + 198, + 208, + 169, + 44, + 252, + 195, + 102, + 172, + 249, + 165, + 26, + 166, + 242, + 75, + 220, + 13, + 201, + 215, + 127, + 170, + 158, + 158, + 117, + 140, + 40, + 192, + 68, + 187, + 229, + 169, + 161, + 88, + 250, + 161, + 6, + 2, + 4, + 101, + 19, + 79, + 224, + 162, + 4, + 2, + 2, + 28, + 32, + 163, + 130, + 6, + 160, + 48, + 130, + 6, + 156, + 48, + 130, + 5, + 132, + 160, + 3, + 2, + 1, + 2, + 2, + 9, + 0, + 164, + 96, + 110, + 62, + 174, + 68, + 162, + 62, + 48, + 13, + 6, + 9, + 42, + 134, + 72, + 134, + 247, + 13, + 1, + 1, + 11, + 5, + 0, + 48, + 129, + 180, + 49, + 11, + 48, + 9, + 6, + 3, + 85, + 4, + 6, + 19, + 2, + 85, + 83, + 49, + 16, + 48, + 14, + 6, + 3, + 85, + 4, + 8, + 19, + 7, + 65, + 114, + 105, + 122, + 111, + 110, + 97, + 49, + 19, + 48, + 17, + 6, + 3, + 85, + 4, + 7, + 19, + 10, + 83, + 99, + 111, + 116, + 116, + 115, + 100, + 97, + 108, + 101, + 49, + 26, + 48, + 24, + 6, + 3, + 85, + 4, + 10, + 19, + 17, + 71, + 111, + 68, + 97, + 100, + 100, + 121, + 46, + 99, + 111, + 109, + 44, + 32, + 73, + 110, + 99, + 46, + 49, + 45, + 48, + 43, + 6, + 3, + 85, + 4, + 11, + 19, + 36, + 104, + 116, + 116, + 112, + 58, + 47, + 47, + 99, + 101, + 114, + 116, + 115, + 46, + 103, + 111, + 100, + 97, + 100, + 100, + 121, + 46, + 99, + 111, + 109, + 47, + 114, + 101, + 112, + 111, + 115, + 105, + 116, + 111, + 114, + 121, + 47, + 49, + 51, + 48, + 49, + 6, + 3, + 85, + 4, + 3, + 19, + 42, + 71, + 111, + 32, + 68, + 97, + 100, + 100, + 121, + 32, + 83, + 101, + 99, + 117, + 114, + 101, + 32, + 67, + 101, + 114, + 116, + 105, + 102, + 105, + 99, + 97, + 116, + 101, + 32, + 65, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121, + 32, + 45, + 32, + 71, + 50, + 48, + 30, + 23, + 13, + 50, + 51, + 48, + 51, + 50, + 54, + 48, + 55, + 51, + 57, + 49, + 56, + 90, + 23, + 13, + 50, + 52, + 48, + 52, + 50, + 54, + 48, + 55, + 51, + 57, + 49, + 56, + 90, + 48, + 27, + 49, + 25, + 48, + 23, + 6, + 3, + 85, + 4, + 3, + 19, + 16, + 97, + 112, + 105, + 46, + 116, + 101, + 108, + 101, + 103, + 114, + 97, + 109, + 46, + 111, + 114, + 103, + 48, + 130, + 1, + 34, + 48, + 13, + 6, + 9, + 42, + 134, + 72, + 134, + 247, + 13, + 1, + 1, + 1, + 5, + 0, + 3, + 130, + 1, + 15, + 0, + 48, + 130, + 1, + 10, + 2, + 130, + 1, + 1, + 0, + 180, + 163, + 22, + 158, + 92, + 87, + 201, + 137, + 101, + 237, + 234, + 120, + 11, + 174, + 138, + 88, + 47, + 174, + 90, + 200, + 110, + 73, + 141, + 252, + 87, + 165, + 152, + 136, + 120, + 46, + 11, + 60, + 64, + 60, + 33, + 46, + 154, + 148, + 152, + 51, + 167, + 227, + 66, + 167, + 133, + 250, + 208, + 115, + 132, + 1, + 28, + 114, + 57, + 55, + 35, + 181, + 86, + 29, + 67, + 165, + 113, + 20, + 8, + 36, + 165, + 57, + 204, + 222, + 88, + 83, + 148, + 142, + 42, + 66, + 167, + 78, + 45, + 7, + 50, + 158, + 186, + 139, + 211, + 42, + 169, + 158, + 192, + 227, + 206, + 154, + 16, + 150, + 69, + 88, + 122, + 199, + 30, + 69, + 20, + 35, + 146, + 187, + 84, + 130, + 136, + 148, + 73, + 182, + 190, + 129, + 33, + 0, + 41, + 109, + 201, + 206, + 139, + 57, + 58, + 220, + 53, + 21, + 217, + 235, + 71, + 156, + 239, + 186, + 9, + 14, + 22, + 228, + 217, + 235, + 114, + 48, + 250, + 73, + 171, + 152, + 49, + 124, + 179, + 172, + 43, + 41, + 145, + 135, + 8, + 65, + 114, + 94, + 53, + 199, + 135, + 4, + 34, + 245, + 72, + 118, + 48, + 109, + 136, + 223, + 242, + 165, + 41, + 19, + 112, + 179, + 135, + 2, + 213, + 107, + 88, + 177, + 232, + 115, + 199, + 228, + 239, + 121, + 134, + 164, + 7, + 95, + 103, + 180, + 121, + 141, + 164, + 37, + 1, + 130, + 140, + 224, + 48, + 23, + 203, + 75, + 92, + 251, + 235, + 76, + 18, + 81, + 185, + 201, + 4, + 31, + 126, + 210, + 248, + 186, + 245, + 53, + 141, + 138, + 28, + 55, + 130, + 240, + 21, + 115, + 0, + 110, + 61, + 28, + 118, + 139, + 1, + 116, + 129, + 61, + 228, + 44, + 167, + 204, + 47, + 102, + 220, + 68, + 168, + 39, + 63, + 234, + 208, + 167, + 168, + 241, + 203, + 234, + 218, + 7, + 56, + 189, + 2, + 3, + 1, + 0, + 1, + 163, + 130, + 3, + 71, + 48, + 130, + 3, + 67, + 48, + 12, + 6, + 3, + 85, + 29, + 19, + 1, + 1, + 255, + 4, + 2, + 48, + 0, + 48, + 29, + 6, + 3, + 85, + 29, + 37, + 4, + 22, + 48, + 20, + 6, + 8, + 43, + 6, + 1, + 5, + 5, + 7, + 3, + 1, + 6, + 8, + 43, + 6, + 1, + 5, + 5, + 7, + 3, + 2, + 48, + 14, + 6, + 3, + 85, + 29, + 15, + 1, + 1, + 255, + 4, + 4, + 3, + 2, + 5, + 160, + 48, + 56, + 6, + 3, + 85, + 29, + 31, + 4, + 49, + 48, + 47, + 48, + 45, + 160, + 43, + 160, + 41, + 134, + 39, + 104, + 116, + 116, + 112, + 58, + 47, + 47, + 99, + 114, + 108, + 46, + 103, + 111, + 100, + 97, + 100, + 100, + 121, + 46, + 99, + 111, + 109, + 47, + 103, + 100, + 105, + 103, + 50, + 115, + 49, + 45, + 53, + 51, + 57, + 53, + 46, + 99, + 114, + 108, + 48, + 93, + 6, + 3, + 85, + 29, + 32, + 4, + 86, + 48, + 84, + 48, + 72, + 6, + 11, + 96, + 134, + 72, + 1, + 134, + 253, + 109, + 1, + 7, + 23, + 1, + 48, + 57, + 48, + 55, + 6, + 8, + 43, + 6, + 1, + 5, + 5, + 7, + 2, + 1, + 22, + 43, + 104, + 116, + 116, + 112, + 58, + 47, + 47, + 99, + 101, + 114, + 116, + 105, + 102, + 105, + 99, + 97, + 116, + 101, + 115, + 46, + 103, + 111, + 100, + 97, + 100, + 100, + 121, + 46, + 99, + 111, + 109, + 47, + 114, + 101, + 112, + 111, + 115, + 105, + 116, + 111, + 114, + 121, + 47, + 48, + 8, + 6, + 6, + 103, + 129, + 12, + 1, + 2, + 1, + 48, + 118, + 6, + 8, + 43, + 6, + 1, + 5, + 5, + 7, + 1, + 1, + 4, + 106, + 48, + 104, + 48, + 36, + 6, + 8, + 43, + 6, + 1, + 5, + 5, + 7, + 48, + 1, + 134, + 24, + 104, + 116, + 116, + 112, + 58, + 47, + 47, + 111, + 99, + 115, + 112, + 46, + 103, + 111, + 100, + 97, + 100, + 100, + 121, + 46, + 99, + 111, + 109, + 47, + 48, + 64, + 6, + 8, + 43, + 6, + 1, + 5, + 5, + 7, + 48, + 2, + 134, + 52, + 104, + 116, + 116, + 112, + 58, + 47, + 47, + 99, + 101, + 114, + 116, + 105, + 102, + 105, + 99, + 97, + 116, + 101, + 115, + 46, + 103, + 111, + 100, + 97, + 100, + 100, + 121, + 46, + 99, + 111, + 109, + 47, + 114, + 101, + 112, + 111, + 115, + 105, + 116, + 111, + 114, + 121, + 47, + 103, + 100, + 105, + 103, + 50, + 46, + 99, + 114, + 116, + 48, + 31, + 6, + 3, + 85, + 29, + 35, + 4, + 24, + 48, + 22, + 128, + 20, + 64, + 194, + 189, + 39, + 142, + 204, + 52, + 131, + 48, + 162, + 51, + 215, + 251, + 108, + 179, + 240, + 180, + 44, + 128, + 206, + 48, + 49, + 6, + 3, + 85, + 29, + 17, + 4, + 42, + 48, + 40, + 130, + 16, + 97, + 112, + 105, + 46, + 116, + 101, + 108, + 101, + 103, + 114, + 97, + 109, + 46, + 111, + 114, + 103, + 130, + 20, + 119, + 119, + 119, + 46, + 97, + 112, + 105, + 46, + 116, + 101, + 108, + 101, + 103, + 114, + 97, + 109, + 46, + 111, + 114, + 103, + 48, + 29, + 6, + 3, + 85, + 29, + 14, + 4, + 22, + 4, + 20, + 5, + 20, + 208, + 192, + 195, + 239, + 14, + 148, + 187, + 33, + 153, + 231, + 163, + 54, + 92, + 40, + 119, + 48, + 150, + 213, + 48, + 130, + 1, + 126, + 6, + 10, + 43, + 6, + 1, + 4, + 1, + 214, + 121, + 2, + 4, + 2, + 4, + 130, + 1, + 110, + 4, + 130, + 1, + 106, + 1, + 104, + 0, + 118, + 0, + 238, + 205, + 208, + 100, + 213, + 219, + 26, + 206, + 197, + 92, + 183, + 157, + 180, + 205, + 19, + 162, + 50, + 135, + 70, + 124, + 188, + 236, + 222, + 195, + 81, + 72, + 89, + 70, + 113, + 31, + 181, + 155, + 0, + 0, + 1, + 135, + 28, + 219, + 122, + 227, + 0, + 0, + 4, + 3, + 0, + 71, + 48, + 69, + 2, + 32, + 50, + 191, + 9, + 112, + 138, + 110, + 88, + 152, + 46, + 199, + 97, + 31, + 100, + 211, + 251, + 20, + 83, + 216, + 13, + 55, + 189, + 104, + 176, + 220, + 79, + 124, + 144, + 73, + 113, + 174, + 150, + 109, + 2, + 33, + 0, + 138, + 223, + 27, + 8, + 53, + 108, + 26, + 182, + 181, + 74, + 159, + 109, + 74, + 137, + 86, + 61, + 40, + 35, + 252, + 193, + 176, + 57, + 212, + 145, + 247, + 139, + 240, + 89, + 61, + 88, + 176, + 211, + 0, + 119, + 0, + 72, + 176, + 227, + 107, + 218, + 166, + 71, + 52, + 15, + 229, + 106, + 2, + 250, + 157, + 48, + 235, + 28, + 82, + 1, + 203, + 86, + 221, + 44, + 129, + 217, + 187, + 191, + 171, + 57, + 216, + 132, + 115, + 0, + 0, + 1, + 135, + 28, + 219, + 123, + 188, + 0, + 0, + 4, + 3, + 0, + 72, + 48, + 70, + 2, + 33, + 0, + 199, + 191, + 203, + 210, + 140, + 109, + 147, + 9, + 6, + 126, + 162, + 136, + 200, + 107, + 63, + 240, + 155, + 133, + 143, + 148, + 9, + 63, + 225, + 230, + 175, + 220, + 20, + 118, + 185, + 214, + 156, + 78, + 2, + 33, + 0, + 162, + 118, + 162, + 21, + 237, + 133, + 249, + 71, + 114, + 217, + 121, + 211, + 17, + 138, + 175, + 119, + 194, + 166, + 168, + 139, + 88, + 219, + 155, + 218, + 72, + 128, + 1, + 80, + 146, + 41, + 134, + 30, + 0, + 117, + 0, + 218, + 182, + 191, + 107, + 63, + 181, + 182, + 34, + 159, + 155, + 194, + 187, + 92, + 107, + 232, + 112, + 145, + 113, + 108, + 187, + 81, + 132, + 133, + 52, + 189, + 164, + 61, + 48, + 72, + 215, + 251, + 171, + 0, + 0, + 1, + 135, + 28, + 219, + 124, + 45, + 0, + 0, + 4, + 3, + 0, + 70, + 48, + 68, + 2, + 32, + 37, + 240, + 252, + 198, + 52, + 50, + 188, + 253, + 37, + 238, + 233, + 249, + 212, + 93, + 25, + 184, + 83, + 191, + 55, + 199, + 96, + 216, + 209, + 71, + 110, + 40, + 164, + 226, + 103, + 70, + 158, + 124, + 2, + 32, + 96, + 253, + 231, + 235, + 124, + 165, + 102, + 237, + 109, + 96, + 186, + 86, + 113, + 81, + 222, + 198, + 203, + 137, + 97, + 143, + 90, + 204, + 179, + 188, + 143, + 94, + 197, + 79, + 86, + 77, + 169, + 225, + 48, + 13, + 6, + 9, + 42, + 134, + 72, + 134, + 247, + 13, + 1, + 1, + 11, + 5, + 0, + 3, + 130, + 1, + 1, + 0, + 34, + 168, + 129, + 97, + 123, + 197, + 117, + 113, + 26, + 200, + 92, + 120, + 44, + 65, + 168, + 60, + 154, + 179, + 244, + 11, + 112, + 79, + 39, + 12, + 185, + 203, + 236, + 10, + 135, + 103, + 232, + 44, + 130, + 236, + 25, + 66, + 168, + 36, + 137, + 230, + 93, + 228, + 203, + 8, + 66, + 156, + 245, + 76, + 83, + 15, + 238, + 168, + 191, + 202, + 217, + 246, + 142, + 63, + 71, + 125, + 82, + 14, + 235, + 200, + 248, + 101, + 49, + 168, + 207, + 126, + 104, + 187, + 40, + 90, + 85, + 88, + 162, + 124, + 146, + 85, + 246, + 112, + 200, + 179, + 106, + 116, + 103, + 5, + 210, + 203, + 76, + 228, + 149, + 33, + 142, + 90, + 242, + 150, + 124, + 142, + 1, + 184, + 73, + 27, + 14, + 245, + 199, + 189, + 34, + 204, + 140, + 33, + 248, + 206, + 73, + 145, + 12, + 71, + 131, + 24, + 110, + 126, + 125, + 212, + 80, + 142, + 44, + 114, + 212, + 27, + 33, + 186, + 223, + 30, + 165, + 78, + 129, + 112, + 240, + 108, + 14, + 249, + 243, + 245, + 17, + 50, + 134, + 28, + 243, + 173, + 31, + 32, + 219, + 37, + 229, + 160, + 174, + 56, + 199, + 37, + 255, + 58, + 254, + 126, + 136, + 60, + 178, + 16, + 115, + 155, + 240, + 194, + 237, + 107, + 57, + 43, + 124, + 1, + 118, + 3, + 109, + 251, + 55, + 5, + 244, + 24, + 172, + 200, + 248, + 225, + 20, + 223, + 243, + 94, + 208, + 209, + 10, + 232, + 230, + 84, + 131, + 122, + 253, + 36, + 4, + 161, + 131, + 183, + 4, + 105, + 195, + 123, + 2, + 27, + 74, + 244, + 109, + 190, + 51, + 191, + 208, + 127, + 192, + 119, + 224, + 199, + 166, + 245, + 12, + 48, + 91, + 245, + 56, + 137, + 152, + 77, + 179, + 68, + 227, + 32, + 160, + 97, + 62, + 30, + 199, + 129, + 123, + 43, + 27, + 31, + 38, + 143, + 179, + 181, + 166, + 122, + 164, + 2, + 4, + 0, + 166, + 18, + 4, + 16, + 97, + 112, + 105, + 46, + 116, + 101, + 108, + 101, + 103, + 114, + 97, + 109, + 46, + 111, + 114, + 103, + 169, + 4, + 2, + 2, + 2, + 88, + 170, + 129, + 243, + 4, + 129, + 240, + 86, + 66, + 161, + 237, + 13, + 127, + 69, + 148, + 53, + 137, + 136, + 30, + 56, + 41, + 120, + 154, + 91, + 238, + 236, + 139, + 172, + 51, + 34, + 252, + 57, + 111, + 157, + 9, + 31, + 137, + 252, + 117, + 23, + 38, + 58, + 224, + 119, + 65, + 191, + 216, + 21, + 0, + 243, + 77, + 104, + 44, + 103, + 154, + 21, + 213, + 60, + 11, + 37, + 142, + 36, + 179, + 78, + 230, + 179, + 233, + 254, + 136, + 160, + 150, + 169, + 54, + 7, + 80, + 42, + 58, + 180, + 99, + 210, + 126, + 24, + 223, + 180, + 107, + 115, + 214, + 238, + 62, + 9, + 55, + 239, + 47, + 163, + 77, + 43, + 191, + 137, + 152, + 199, + 176, + 164, + 98, + 189, + 136, + 78, + 35, + 253, + 163, + 201, + 111, + 47, + 134, + 28, + 253, + 100, + 150, + 214, + 177, + 70, + 166, + 78, + 39, + 128, + 88, + 219, + 231, + 4, + 90, + 62, + 157, + 17, + 58, + 58, + 175, + 170, + 196, + 86, + 1, + 81, + 23, + 194, + 147, + 180, + 39, + 93, + 160, + 89, + 93, + 213, + 16, + 48, + 105, + 133, + 145, + 209, + 194, + 217, + 229, + 103, + 199, + 69, + 48, + 248, + 210, + 199, + 128, + 55, + 118, + 243, + 239, + 161, + 135, + 176, + 157, + 145, + 44, + 101, + 61, + 200, + 81, + 180, + 46, + 39, + 210, + 233, + 37, + 46, + 72, + 56, + 173, + 20, + 103, + 184, + 138, + 62, + 223, + 195, + 7, + 186, + 211, + 191, + 143, + 138, + 10, + 131, + 236, + 57, + 109, + 250, + 53, + 151, + 229, + 181, + 205, + 19, + 151, + 196, + 211, + 114, + 5, + 219, + 201, + 229, + 220, + 176, + 136, + 177, + 15, + 91, + 24, + 211, + 87, + 65, + 218, + 252, + 249, + 15, + 217, + 160, + 47, + 111, + 196, + 94, + 52, + 225, + 167, + 174, + 7, + 2, + 5, + 0, + 218, + 165, + 102, + 102, + 179, + 3, + 2, + 1, + 29 + ] + } + }, + "list": [ + "api.telegram.org:443:::::::::::::::::::::" + ] + } + }, + "testEnv": false + } + }, + "botInfo": { + "id": 6489664401, + "is_bot": true, + "first_name": "CampFire", + "username": "CampFireGameBot", + "can_join_groups": true, + "can_read_all_group_messages": false, + "supports_inline_queries": false + }, + "state": {}, + "match": [ + "{type: business_invite_accept", + "accept" + ] +} \ No newline at end of file diff --git a/json/rarecars.json b/json/rarecars.json index cfa8033..4f2b2b9 100644 --- a/json/rarecars.json +++ b/json/rarecars.json @@ -93,5 +93,10 @@ "name": "Ferrari F8", "price": 34000000, "image": "https://avatars.mds.yandex.net/get-autoru-vos/2037331/cd075cbfc2d10c05bb0450dcc889d351/1200x900n" + }, + { + "name": "Mercedes-Benz AMG GT S, 2017", + "price": 10500000, + "image": "https://avatars.mds.yandex.net/get-autoru-vos/2159790/270111424b42001ae010abc3367bcda9/1200x900n" } ] \ No newline at end of file diff --git a/json/simplecars.json b/json/simplecars.json index cc30e92..a5e8be7 100644 --- a/json/simplecars.json +++ b/json/simplecars.json @@ -53,5 +53,10 @@ "name": "Mazda 3", "price": 500000, "image": "https://a.d-cd.net/da371e4s-1920.jpg" + }, + { + "name": "Hot Wheels Lamborghini Sian FKP 37 Orange Коллекционная", + "price": 1000, + "image": "https://ir.ozone.ru/s3/multimedia-4/wc700/6769855444.jpg" } ] \ No newline at end of file diff --git a/json/weaponshop.json b/json/weaponshop.json index 6200cb1..dea5b33 100644 --- a/json/weaponshop.json +++ b/json/weaponshop.json @@ -1,52 +1,57 @@ { "0": { - "name": "M1911", - "price": 13000, + "name": "HK UMP", + "price": 33999, + "damage": 0.028, "type": "weapon" }, "1": { - "name": "ПМ", - "price": 13000, + "name": "Glock 17", + "price": 7999, + "damage": 0.013, "type": "weapon" }, "2": { - "name": "АКС74У", - "price": 34999, + "name": "HK UMP", + "price": 33999, + "damage": 0.028, "type": "weapon" }, "3": { - "name": "G36C", - "price": 38999, + "name": "АКС74У", + "price": 34999, + "damage": 0.031, "type": "weapon" }, "4": { - "name": "G36C", - "price": 38999, + "name": "M1911", + "price": 13000, + "damage": 0.018, "type": "weapon" }, "5": { - "name": "Бронежилет M1", - "price": 25000, + "name": "Шлем танкиста", + "price": 1000, "type": "equipment" }, "6": { - "name": "Бронежилет M2", - "price": 35000, + "name": "Бронежилет M5", + "price": 1000, "type": "equipment" }, "7": { - "name": "Бронежилет M1", - "price": 25000, + "name": "Бронежилет M4", + "price": 1000, "type": "equipment" }, "8": { - "name": "Бронежилет M2", - "price": 35000, + "name": "Бронежилет M5", + "price": 1000, "type": "equipment" }, "9": { - "name": "Бронежилет M3", - "price": 60000, + "name": "Кольчуга", + "price": 1000, "type": "equipment" } } \ No newline at end of file diff --git a/media/Thumbs.db b/media/Thumbs.db new file mode 100644 index 0000000000000000000000000000000000000000..db80c43d83be1cc97dfe12047d4973f59e1a92b5 GIT binary patch literal 6144 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 lA^&-OW#j-zq7o3@ZQt002ovPDHLkV1h(8V)y_6 delta 70841 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" } }, + "node_modules/@opencensus/core": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.9.tgz", + "integrity": "sha512-31Q4VWtbzXpVUd2m9JS6HEaPjlKvNMOiF7lWKNmXF84yUcgfAFL5re7/hjDmdyQbOp32oGc+RFV78jXIldVz6Q==", + "dependencies": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^5.5.0", + "shimmer": "^1.2.0", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/core/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/@opencensus/propagation-b3": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@opencensus/propagation-b3/-/propagation-b3-0.0.8.tgz", + "integrity": "sha512-PffXX2AL8Sh0VHQ52jJC4u3T0H6wDK6N/4bg7xh4ngMYOIi13aR1kzVvX1sVDBgfGwDOkMbl4c54Xm3tlPx/+A==", + "dependencies": { + "@opencensus/core": "^0.0.8", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/propagation-b3/node_modules/@opencensus/core": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.8.tgz", + "integrity": "sha512-yUFT59SFhGMYQgX0PhoTR0LBff2BEhPrD9io1jWfF/VDbakRfs6Pq60rjv0Z7iaTav5gQlttJCX2+VPxFWCuoQ==", + "dependencies": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^5.5.0", + "shimmer": "^1.2.0", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/propagation-b3/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/@pm2/agent": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.3.tgz", + "integrity": "sha512-xkqqCoTf5VsciMqN0vb9jthW7olVAi4KRFNddCc7ZkeJZ3i8QwZANr4NSH2H5DvseRFHq7MiPspRY/EWAFWWTg==", + "dependencies": { + "async": "~3.2.0", + "chalk": "~3.0.0", + "dayjs": "~1.8.24", + "debug": "~4.3.1", + "eventemitter2": "~5.0.1", + "fast-json-patch": "^3.0.0-1", + "fclone": "~1.0.11", + "nssocket": "0.6.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.0", + "proxy-agent": "~6.3.0", + "semver": "~7.5.0", + "ws": "~7.4.0" + } + }, + "node_modules/@pm2/agent/node_modules/dayjs": { + "version": "1.8.36", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz", + "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==" + }, + "node_modules/@pm2/agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@pm2/agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@pm2/agent/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pm2/io": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-5.0.2.tgz", + "integrity": "sha512-XAvrNoQPKOyO/jJyCu8jPhLzlyp35MEf7w/carHXmWKddPzeNOFSEpSEqMzPDawsvpxbE+i918cNN+MwgVsStA==", + "dependencies": { + "@opencensus/core": "0.0.9", + "@opencensus/propagation-b3": "0.0.8", + "async": "~2.6.1", + "debug": "~4.3.1", + "eventemitter2": "^6.3.1", + "require-in-the-middle": "^5.0.0", + "semver": "~7.5.4", + "shimmer": "^1.2.0", + "signal-exit": "^3.0.3", + "tslib": "1.9.3" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@pm2/io/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/@pm2/io/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@pm2/io/node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + }, + "node_modules/@pm2/io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@pm2/io/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pm2/js-api": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.6.7.tgz", + "integrity": "sha512-jiJUhbdsK+5C4zhPZNnyA3wRI01dEc6a2GhcQ9qI38DyIk+S+C8iC3fGjcjUbt/viLYKPjlAaE+hcT2/JMQPXw==", + "dependencies": { + "async": "^2.6.3", + "axios": "^0.21.0", + "debug": "~4.3.1", + "eventemitter2": "^6.3.1", + "ws": "^7.0.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@pm2/js-api/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/@pm2/js-api/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@pm2/js-api/node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + }, + "node_modules/@pm2/js-api/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@pm2/pm2-version-check": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz", + "integrity": "sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==", + "dependencies": { + "debug": "^4.3.1" + } + }, + "node_modules/@pm2/pm2-version-check/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@pm2/pm2-version-check/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -107,6 +375,11 @@ "resolved": "https://registry.npmjs.org/@telegraf/types/-/types-6.8.1.tgz", "integrity": "sha512-JCRQuPPDCreYQaAeOwnqIlWrs8pJVvaNEUWBVNvdK3oJoTUKyBV+3TsPrIcnGqLeapptznuTk5s4udTlZPvGTA==" }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, "node_modules/@types/node": { "version": "14.14.41", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", @@ -175,6 +448,19 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/amp": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", + "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==" + }, + "node_modules/amp-message": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz", + "integrity": "sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==", + "dependencies": { + "amp": "0.3.1" + } + }, "node_modules/ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -196,6 +482,14 @@ "node": ">=6" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -265,6 +559,19 @@ "node": ">= 6" } }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argparse/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, "node_modules/array.prototype.findindex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array.prototype.findindex/-/array.prototype.findindex-2.1.0.tgz", @@ -290,6 +597,39 @@ "node": ">=0.8" } }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/async-listener": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", + "integrity": "sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw==", + "dependencies": { + "semver": "^5.3.0", + "shimmer": "^1.1.0" + }, + "engines": { + "node": "<=0.11.8 || >0.11.10" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -308,11 +648,27 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/basic-ftp": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", + "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -338,11 +694,27 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/blessed": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", + "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==", + "bin": { + "blessed": "bin/tput.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "node_modules/bodec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", + "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==" + }, "node_modules/boxen": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", @@ -403,6 +775,11 @@ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -529,24 +906,35 @@ "node": ">=8" } }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==" + }, "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { - "fsevents": "~2.3.1" + "fsevents": "~2.3.2" } }, "node_modules/chownr": { @@ -573,6 +961,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-tableau": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz", + "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==", + "dependencies": { + "chalk": "3.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -616,6 +1015,11 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -642,11 +1046,25 @@ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, + "node_modules/continuation-local-storage": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", + "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", + "dependencies": { + "async-listener": "^0.6.0", + "emitter-listener": "^1.1.1" + } + }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "node_modules/croner": { + "version": "4.1.97", + "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" + }, "node_modules/crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -660,6 +1078,11 @@ "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.5.0.tgz", "integrity": "sha512-RxruSK3M4XgzcD7Trm2wEN+SJ26ChIb903+IWxNOcB5q4jT2Cs+hFr6QP39J05EohshRFEvyzEBoZ/466S2sbw==" }, + "node_modules/culvert": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", + "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==" + }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -671,6 +1094,14 @@ "node": ">=0.10" } }, + "node_modules/data-uri-to-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", + "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", + "engines": { + "node": ">= 14" + } + }, "node_modules/date-fns": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", @@ -686,6 +1117,11 @@ "url": "https://opencollective.com/date-fns" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, "node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -729,6 +1165,19 @@ "node": ">= 0.4" } }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -799,6 +1248,14 @@ "safer-buffer": "^2.1.0" } }, + "node_modules/emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "dependencies": { + "shimmer": "^1.2.0" + } + }, "node_modules/emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -812,6 +1269,25 @@ "once": "^1.4.0" } }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dependencies": { + "stackframe": "^1.3.4" + } + }, "node_modules/es-abstract": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", @@ -865,6 +1341,65 @@ "node": ">=8" } }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -873,6 +1408,11 @@ "node": ">=6" } }, + "node_modules/eventemitter2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", + "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==" + }, "node_modules/eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -896,11 +1436,21 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" + }, "node_modules/file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", @@ -920,6 +1470,25 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -946,6 +1515,19 @@ "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -1062,6 +1644,41 @@ "once": "^1.3.1" } }, + "node_modules/get-uri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", + "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^5.0.1", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/get-uri/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -1070,6 +1687,16 @@ "assert-plus": "^1.0.0" } }, + "node_modules/git-node-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", + "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==" + }, + "node_modules/git-sha1": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", + "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -1217,6 +1844,50 @@ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1264,6 +1935,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -1312,6 +1994,11 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==" }, + "node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + }, "node_modules/is-bigint": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", @@ -1367,6 +2054,17 @@ "is-ci": "bin.js" } }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", @@ -1534,6 +2232,17 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "node_modules/js-git": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", + "integrity": "sha512-+E5ZH/HeRnoc/LW0AmAyhU+mNcWBzAKE+30+IDMLSLbbK+Tdt02AdkOKq9u15rlJsDEGFqtgckc8ZM59LhhiUA==", + "dependencies": { + "bodec": "^0.1.0", + "culvert": "^0.1.2", + "git-sha1": "^0.1.2", + "pako": "^0.2.5" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -1559,6 +2268,14 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1592,11 +2309,27 @@ "node": ">=8" } }, + "node_modules/lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==", + "engines": { + "node": ">=0.2.0" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "engines": { + "node": ">=0.8.6" + } + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -1734,6 +2467,11 @@ "node": ">=10" } }, + "node_modules/module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + }, "node_modules/moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", @@ -1766,6 +2504,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "node_modules/nan": { "version": "2.18.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", @@ -1776,6 +2519,30 @@ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" }, + "node_modules/needle": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -1885,6 +2652,23 @@ "set-blocking": "^2.0.0" } }, + "node_modules/nssocket": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", + "integrity": "sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==", + "dependencies": { + "eventemitter2": "~0.4.14", + "lazy": "~1.0.11" + }, + "engines": { + "node": ">= 0.10.x" + } + }, + "node_modules/nssocket/node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" + }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -1958,6 +2742,81 @@ "node": ">=10" } }, + "node_modules/pac-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "pac-resolver": "^7.0.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/pac-resolver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", + "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "dependencies": { + "degenerator": "^5.0.0", + "ip": "^1.1.8", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -1985,6 +2844,11 @@ "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1993,6 +2857,11 @@ "node": ">=0.10.0" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -2094,6 +2963,235 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidusage": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz", + "integrity": "sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==", + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pm2": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.3.0.tgz", + "integrity": "sha512-xscmQiAAf6ArVmKhjKTeeN8+Td7ZKnuZFFPw1DGkdFPR/0Iyx+m+1+OpCdf9+HQopX3VPc9/wqPQHqVOfHum9w==", + "dependencies": { + "@pm2/agent": "~2.0.0", + "@pm2/io": "~5.0.0", + "@pm2/js-api": "~0.6.7", + "@pm2/pm2-version-check": "latest", + "async": "~3.2.0", + "blessed": "0.1.81", + "chalk": "3.0.0", + "chokidar": "^3.5.3", + "cli-tableau": "^2.0.0", + "commander": "2.15.1", + "croner": "~4.1.92", + "dayjs": "~1.11.5", + "debug": "^4.3.1", + "enquirer": "2.3.6", + "eventemitter2": "5.0.1", + "fclone": "1.0.11", + "mkdirp": "1.0.4", + "needle": "2.4.0", + "pidusage": "~3.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.1", + "pm2-deploy": "~1.0.2", + "pm2-multimeter": "^0.1.2", + "promptly": "^2", + "semver": "^7.2", + "source-map-support": "0.5.21", + "sprintf-js": "1.1.2", + "vizion": "~2.2.1", + "yamljs": "0.3.0" + }, + "bin": { + "pm2": "bin/pm2", + "pm2-dev": "bin/pm2-dev", + "pm2-docker": "bin/pm2-docker", + "pm2-runtime": "bin/pm2-runtime" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "pm2-sysmonit": "^1.2.8" + } + }, + "node_modules/pm2-axon": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz", + "integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==", + "dependencies": { + "amp": "~0.3.1", + "amp-message": "~0.1.1", + "debug": "^4.3.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/pm2-axon-rpc": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz", + "integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==", + "dependencies": { + "debug": "^4.3.1" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/pm2-axon-rpc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/pm2-axon-rpc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/pm2-axon/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/pm2-axon/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/pm2-deploy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-1.0.2.tgz", + "integrity": "sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==", + "dependencies": { + "run-series": "^1.1.8", + "tv4": "^1.3.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pm2-multimeter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz", + "integrity": "sha512-S+wT6XfyKfd7SJIBqRgOctGxaBzUOmVQzTAS+cg04TsEUObJVreha7lvCfX8zzGVr871XwCSnHUU7DQQ5xEsfA==", + "dependencies": { + "charm": "~0.1.1" + } + }, + "node_modules/pm2-sysmonit": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz", + "integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==", + "optional": true, + "dependencies": { + "async": "^3.2.0", + "debug": "^4.3.1", + "pidusage": "^2.0.21", + "systeminformation": "^5.7", + "tx2": "~1.0.4" + } + }, + "node_modules/pm2-sysmonit/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/pm2-sysmonit/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/pm2-sysmonit/node_modules/pidusage": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", + "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", + "optional": true, + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pm2/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/pm2/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/pm2/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -2150,6 +3248,89 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/promptly": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", + "integrity": "sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==", + "dependencies": { + "read": "^1.0.4" + } + }, + "node_modules/proxy-agent": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -2210,6 +3391,17 @@ "rc": "cli.js" } }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -2230,9 +3422,9 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dependencies": { "picomatch": "^2.2.1" }, @@ -2339,6 +3531,56 @@ "uuid": "bin/uuid" } }, + "node_modules/require-in-the-middle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", + "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/require-in-the-middle/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/require-in-the-middle/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -2369,6 +3611,25 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-series": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", + "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2409,6 +3670,11 @@ "node": ">= 0.10" } }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + }, "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -2535,6 +3801,11 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, "node_modules/shortid": { "version": "2.2.16", "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", @@ -2600,6 +3871,95 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socks/node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/split2": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", @@ -2621,6 +3981,11 @@ "node": ">= 6" } }, + "node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + }, "node_modules/sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -2645,6 +4010,11 @@ "node": ">=0.10.0" } }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, "node_modules/stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", @@ -2765,6 +4135,43 @@ "node": ">=4" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/systeminformation": { + "version": "5.21.9", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.21.9.tgz", + "integrity": "sha512-7pI4mu9P/2MGDV0T49B52E7IULBGj+kRVk6JSYUj5qfAk7N7C7aNX15fXziqrbgZntc6/jjYzWeb/x41jhg/eA==", + "optional": true, + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, "node_modules/tar": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", @@ -2886,6 +4293,11 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -2897,11 +4309,28 @@ "node": "*" } }, + "node_modules/tv4": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", + "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "node_modules/tx2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz", + "integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==", + "optional": true, + "dependencies": { + "json-stringify-safe": "^5.0.1" + } + }, "node_modules/type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -2969,6 +4398,14 @@ "node": ">=8" } }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/update-notifier": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", @@ -3052,6 +4489,28 @@ "extsprintf": "^1.2.0" } }, + "node_modules/vizion": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vizion/-/vizion-2.2.1.tgz", + "integrity": "sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==", + "dependencies": { + "async": "^2.6.3", + "git-node-fs": "^1.0.0", + "ini": "^1.3.5", + "js-git": "^0.7.8" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vizion/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, "node_modules/voucher-code-generator": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/voucher-code-generator/-/voucher-code-generator-1.3.0.tgz", @@ -3129,6 +4588,26 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xdg-basedir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", @@ -3149,6 +4628,19 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "dependencies": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + }, + "bin": { + "json2yaml": "bin/json2yaml", + "yaml2json": "bin/yaml2json" + } } } } diff --git a/package.json b/package.json index 61fbef4..7d4c867 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,13 @@ "canvas": "^2.11.2", "date-fns": "^2.30.0", "dotenv": "^16.3.1", + "error-stack-parser": "^2.1.4", "fs": "^0.0.1-security", "node-telegram-bot-api": "^0.52.0", "nodemon": "^2.0.7", "pg": "^8.6.0", "pg-hstore": "^2.3.3", + "pm2": "^5.3.0", "prettytable": "^0.3.1", "sequelize": "^6.6.2", "shortid": "^2.2.16", diff --git a/run.ps1 b/run.ps1 new file mode 100644 index 0000000..efba662 --- /dev/null +++ b/run.ps1 @@ -0,0 +1,2 @@ +[System.Console]::Title = 'CampFireGame' +nodemon --ignore json/ .\index.js \ No newline at end of file diff --git a/scenes/crime.js b/scenes/crime.js new file mode 100644 index 0000000..977a720 --- /dev/null +++ b/scenes/crime.js @@ -0,0 +1,56 @@ +const { + Scenes, + Markup +} = require('telegraf') + +const crime = new Scenes.BaseScene('Crime'); + +crime.enter((ctx) => { + ctx.reply('Scene: Выберите ограбление', Markup.inlineKeyboard([ + [ + {text: 'Карманные кражи [SOLO]', callback_data: `POCKET_ACTION`}, + {text: 'Магазин', callback_data: `heist`}, + {text: 'Банкомат', callback_data: `heist`}, + {text: 'Банковское отделение', callback_data: `heist`}, + {text: 'Угон', callback_data: `heist`}, + {text: 'Ювелирка', callback_data: `heist`}, + {text: 'Банк', callback_data: `heist`} + ] + ])) +}); + +crime.action(`POCKET_ACTION`, (ctx) => { + ctx.editMessageText('Scene: Выберите объект', Markup.inlineKeyboard([ + [ + {text: 'Карман', callback_data: `POCKET_TARGET`}, + {text: 'Бумажник', callback_data: `heist`}, + {text: 'Сумка', callback_data: `heist`} + ] +])) +}); + +crime.action(`POCKET_TARGET`, (ctx) => { + if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); + ctx.editMessageText('Scene: В кармане обнаружено', Markup.inlineKeyboard([ + [ + {text: 'Деньги', callback_data: `MONEY`}, + {text: 'Телефон', callback_data: `PHONE`} + ] +])) +}); + +crime.action(`MONEY`, (ctx) => { + if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); + return ctx.editMessageText('Scene: Успех MONEY') +}); + +crime.action(`PHONE`, (ctx) => { + if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); + return ctx.editMessageText('Scene: Успех PHONE') +}); + +crime.leave((ctx) => { + console.log('Завершено'); +}); + +module.exports = crime \ No newline at end of file diff --git a/scenes/heist.js b/scenes/heist.js new file mode 100644 index 0000000..f119105 --- /dev/null +++ b/scenes/heist.js @@ -0,0 +1,56 @@ +const { + Scenes, + Markup +} = require('telegraf') + +const heist = new Scenes.BaseScene('HEIST'); + +heist.enter((ctx) => { + ctx.reply('Scene: Выберите ограбление', Markup.inlineKeyboard([ + [ + {text: 'Карманные кражи', callback_data: `POCKET_ACTION`}, + {text: 'Магазин', callback_data: `heist`}, + {text: 'Банкомат', callback_data: `heist`}, + {text: 'Банковское отделение', callback_data: `heist`}, + {text: 'Угон', callback_data: `heist`}, + {text: 'Ювелирка', callback_data: `heist`}, + {text: 'Банк', callback_data: `heist`} + ] + ])) +}); + +heist.action(`POCKET_ACTION`, (ctx) => { + ctx.editMessageText('Scene: Выберите объект', Markup.inlineKeyboard([ + [ + {text: 'Карман', callback_data: `POCKET_TARGET`}, + {text: 'Бумажник', callback_data: `heist`}, + {text: 'Сумка', callback_data: `heist`} + ] +])) +}); + +heist.action(`POCKET_TARGET`, (ctx) => { + if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); + ctx.editMessageText('Scene: В кармане обнаружено', Markup.inlineKeyboard([ + [ + {text: 'Деньги', callback_data: `MONEY`}, + {text: 'Телефон', callback_data: `PHONE`} + ] +])) +}); + +heist.action(`MONEY`, (ctx) => { + if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); + return ctx.editMessageText('Scene: Успех MONEY') +}); + +heist.action(`PHONE`, (ctx) => { + if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); + return ctx.editMessageText('Scene: Успех PHONE') +}); + +heist.leave((ctx) => { + console.log('Завершено'); +}); + +module.exports = heist \ No newline at end of file diff --git a/scenes/index.js b/scenes/index.js new file mode 100644 index 0000000..0b16fe7 --- /dev/null +++ b/scenes/index.js @@ -0,0 +1,17 @@ +const { + Telegraf, + Scenes, + session, + Stage, + Markup +} = require('telegraf') + +const heistStart = require('./heist') +const testStart = require('./test') + +const stage = new Scenes.Stage( + [heistStart] + ) + + +module.exports = stage \ No newline at end of file diff --git a/scenes/test.js b/scenes/test.js new file mode 100644 index 0000000..984bbcd --- /dev/null +++ b/scenes/test.js @@ -0,0 +1,40 @@ +const { + Telegraf, + Scenes, + Markup +} = require('telegraf') + +const test = new Scenes.BaseScene('TEST'); + +test.enter((ctx) => { +ctx.session.myData = {}; + ctx.reply('Scene: Выберите ограбление', Markup.inlineKeyboard([ + [ + {text: 'Карманные кражи', callback_data: `POCKET_ACTION`}, + {text: 'Магазин', callback_data: `heist`}, + {text: 'Банкомат', callback_data: `heist`}, + {text: 'Банковское отделение', callback_data: `heist`}, + {text: 'Угон', callback_data: `heist`}, + {text: 'Ювелирка', callback_data: `heist`}, + {text: 'Банк', callback_data: `heist`} + ] +])); +}); + +test.action(`POCKET_ACTION`, (ctx) => { +ctx.reply('Выбор'); +ctx.session.myData.preferenceType = 'Pocket'; +return ctx.scene.enter('HEIST'); // switch to some other scene +}); + +test.action(`MOVIE_ACTION`, (ctx) => { +ctx.reply('You choose movie, your loss'); +ctx.session.myData.preferenceType = 'Movie'; +return ctx.scene.leave(); // exit global namespace +}); + +test.leave((ctx) => { +ctx.reply('Thank you for your time!'); +}); + +module.exports = test \ No newline at end of file diff --git a/utils/escape.js b/utils/escape.js new file mode 100644 index 0000000..da5f01c --- /dev/null +++ b/utils/escape.js @@ -0,0 +1,22 @@ +module.exports = (text) => { + text = text + .replace(/\_/g, '\\_') + .replace(/\*/g, '\\*') + .replace(/\[/g, '\\[') + .replace(/\]/g, '\\]') + .replace(/\(/g, '\\(') + .replace(/\)/g, '\\)') + .replace(/\~/g, '\\~') + .replace(/\`/g, '\\`') + .replace(/\>/g, '\\>') + .replace(/\#/g, '\\#') + .replace(/\+/g, '\\+') + .replace(/\-/g, '\\-') + .replace(/\=/g, '\\=') + .replace(/\|/g, '\\|') + .replace(/\{/g, '\\{') + .replace(/\}/g, '\\}') + .replace(/\./g, '\\.') + .replace(/\!/g, '\\!'); + return text +} \ No newline at end of file diff --git a/utils/generatePromo.js b/utils/generatePromo.js new file mode 100644 index 0000000..5bcc5ab --- /dev/null +++ b/utils/generatePromo.js @@ -0,0 +1,37 @@ +const { + Telegraf +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + PromocodeModel, + mainChat +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const voucher_codes = require('voucher-code-generator'); +const rand = require('./rand') +const generateVoucher = require('./generateVoucher'); +const { promoTopicId } = require('../config'); +module.exports = async () => { + let activs = rand(1, 3) + let give = rand(1000, 10000) + let code = voucher_codes.generate({ + length: 6, + count: 1, + prefix: "CMP-", + postfix: "-FIRE", + charset: voucher_codes.charset("alphanumeric") + }); + let promocode = await PromocodeModel.findOne({ + where: { + code: code[0] + } + }) + if(promocode === null){ + await PromocodeModel.create({ + code: code[0], + activations: activs, + money: give + }) + let voucherImage = await generateVoucher(code[0], activs, give) + return await bot.telegram.sendPhoto(mainChat, {source: voucherImage}, {reply_to_message_id: promoTopicId}) + } +} \ No newline at end of file diff --git a/utils/generateVoucher.js b/utils/generateVoucher.js new file mode 100644 index 0000000..8def5a7 --- /dev/null +++ b/utils/generateVoucher.js @@ -0,0 +1,28 @@ +const { createCanvas, loadImage } = require('canvas'); +const fs = require('fs'); + +module.exports = async(code, activations, money) => { + // загружаем изображение фона + const background = await loadImage('./media/imageDefault3.png'); + + // создаем новый canvas + const canvas = createCanvas(background.width, background.height); + const ctx = canvas.getContext('2d'); + + // рисуем фоновое изображение + ctx.drawImage(background, 0, 0); + + // выводим текст на картинку + ctx.font = 'bold 30px Srbija Sans'; + ctx.fillStyle = '#232323'; + ctx.textAlign = 'center'; + ctx.fillText(`${code}`, canvas.width/2, canvas.height/1.90); + + // сохраняем картинку в файл + const out = fs.createWriteStream('./media/image.png'); + const stream = canvas.createPNGStream(); + stream.pipe(out); + + // возвращаем путь к сгенерированной картинке + return './media/image.png'; +} \ No newline at end of file diff --git a/utils/getCurrentTime.js b/utils/getCurrentTime.js new file mode 100644 index 0000000..2049195 --- /dev/null +++ b/utils/getCurrentTime.js @@ -0,0 +1,10 @@ +module.exports = () => { + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth() < 9 ? `0${now.getMonth() + 1}` : now.getMonth() + 1; + const day = now.getDate() < 10 ? `0${now.getDate()}` : now.getDate(); + const hours = now.getHours() < 10 ? `0${now.getHours()}` : now.getHours(); + const minutes = now.getMinutes() < 10 ? `0${now.getMinutes()}` : now.getMinutes(); + const seconds = now.getSeconds() < 10 ? `0${now.getSeconds()}` : now.getSeconds(); + return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`; +} \ No newline at end of file diff --git a/utils/getSlot.js b/utils/getSlot.js new file mode 100644 index 0000000..46fbde1 --- /dev/null +++ b/utils/getSlot.js @@ -0,0 +1,22 @@ +module.exports = (result) => { + switch(result.dice.value){ + case 1: + return 10 + case 22: + return 15 + case 43: + return 20 + case 64: + return 25 + case 17: case 33: case 49: + return 1 + case 6: case 38: case 54: + return 2 + case 11: case 27: case 59: + return 3 + case 16: case 32: case 48: + return 4 + default: + return 0 + } +} \ No newline at end of file diff --git a/utils/giveExp.js b/utils/giveExp.js new file mode 100644 index 0000000..d707400 --- /dev/null +++ b/utils/giveExp.js @@ -0,0 +1,20 @@ +const { + Telegraf + } = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + expToUp + } = require('/workspace/degradin/Dev/Telegram/CampFire Play Dev/config') + + +module.exports = async (user, experience) => { + user.exp += experience + for(i in expToUp){ + if (user.exp >= expToUp[user.level]) { + user.exp -= expToUp[user.level] + user.level += 1 + user.save() + await bot.telegram.sendMessage(user.telegram_id, `⤴️ Ваш уровень повысился до ${user.level}!`)} + } + user.save() +} \ No newline at end of file diff --git a/utils/html-escape.js b/utils/html-escape.js new file mode 100644 index 0000000..623145b --- /dev/null +++ b/utils/html-escape.js @@ -0,0 +1,10 @@ +module.exports = (str) => str.replace( + /[&<>'"]/g, + (tag) => ({ + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }[tag] || tag) + ) \ No newline at end of file diff --git a/utils/index.js b/utils/index.js new file mode 100644 index 0000000..92291bb --- /dev/null +++ b/utils/index.js @@ -0,0 +1,33 @@ +const spaces = require('./spaces') +const spacesWithMarkdown = require('./spacesV2') +const escape = require('./escape') +const generatePromo = require('./generatePromo') +const generateVoucher = require('./generateVoucher') +const getCurrentTime = require('./getCurrentTime') +const getSlot = require('./getSlot') +const giveExp = require('./giveExp') +const matPriceUpdate = require('./matPriceUpdate') +const rand = require('./rand') +const random = require('./random') +const setCooldown = require('./setCooldown') +const weaponShopUpdate = require('./weaponShopUpdate') +const stats = require('./stats') +const escapeHTML = require('./html-escape') + +module.exports = { + spaces, + spacesWithMarkdown, + escape, + generatePromo, + generateVoucher, + getCurrentTime, + getSlot, + giveExp, + matPriceUpdate, + rand, + random, + setCooldown, + weaponShopUpdate, + stats, + escapeHTML +} \ No newline at end of file diff --git a/utils/matPriceUpdate.js b/utils/matPriceUpdate.js new file mode 100644 index 0000000..e477e04 --- /dev/null +++ b/utils/matPriceUpdate.js @@ -0,0 +1,11 @@ +const rand = require('./rand') +const { + WorldModel + } = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') + +module.exports = async () => { + let world = await WorldModel.findByPk(1) + let price = rand(35, 170) + world.matPrice = price + world.save() +} \ No newline at end of file diff --git a/utils/rand.js b/utils/rand.js new file mode 100644 index 0000000..1ff15bc --- /dev/null +++ b/utils/rand.js @@ -0,0 +1,3 @@ +module.exports = (min, max) => { + return Math.round(Math.random() * (max - min)) + min +} \ No newline at end of file diff --git a/utils/random.js b/utils/random.js new file mode 100644 index 0000000..befd9ee --- /dev/null +++ b/utils/random.js @@ -0,0 +1,7 @@ +Array.prototype.random = function() { + return this[Math.floor(this.length * Math.random())]; +} + +module.exports = { + randomArray: Array.prototype.random +}; \ No newline at end of file diff --git a/utils/setCooldown.js b/utils/setCooldown.js new file mode 100644 index 0000000..23dd3ac --- /dev/null +++ b/utils/setCooldown.js @@ -0,0 +1,26 @@ +module.exports = (user, seconds, type) => { + let cooldown = {} + cooldown.currentTime = Math.trunc(Date.now() / 1000) + + switch(user.status){ + case `user`: + cooldown.endTime = Math.trunc(Date.now() / 1000 + seconds) + break; + case `bronze`: + cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*85)) + break; + case `silver`: + cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*75)) + break; + case `gold`: + cooldown.endTime = Math.trunc(Date.now() / 1000 + (seconds/100*50)) + break; + case `admin`: + cooldown.endTime = Math.trunc(Date.now() / 1000) + break; + } + cooldown.timeLeft = cooldown.endTime - cooldown.currentTime + cooldown.timeLeftInMinutes = Math.ceil((type - cooldown.currentTime) / 60) + return cooldown + +} \ No newline at end of file diff --git a/utils/spaces.js b/utils/spaces.js new file mode 100644 index 0000000..03a320e --- /dev/null +++ b/utils/spaces.js @@ -0,0 +1,4 @@ +module.exports = (string) => { + if (typeof string !== "string") string = string.toString(); + return string.split("").reverse().join("").match(/[0-9]{1,3}/g).join(".").split("").reverse().join(""); +} \ No newline at end of file diff --git a/utils/spacesV2.js b/utils/spacesV2.js new file mode 100644 index 0000000..ecdb455 --- /dev/null +++ b/utils/spacesV2.js @@ -0,0 +1,4 @@ +module.exports = (string) => { + if (typeof string !== "string") string = string.toString(); + return string.split("").reverse().join("").match(/[0-9]{1,3}/g).join(".\\").split("").reverse().join(""); +} \ No newline at end of file diff --git a/utils/stats.js b/utils/stats.js new file mode 100644 index 0000000..9aa70c1 --- /dev/null +++ b/utils/stats.js @@ -0,0 +1,61 @@ +const io = require('@pm2/io') + +const stats = { + rpsAvrg: 0, + responseTimeAvrg: 0, + times: {} +} + +const rtOP = io.metric({ + name: 'response time', + unit: 'ms' +}) + +// const usersCountIO = io.metric({ +// name: 'Users count', +// unit: 'user' +// }) + +setInterval(() => { + if (Object.keys(stats.times).length > 1) { + const time = Object.keys(stats.times).shift() + + const sumResponseTime = stats.times[time].reduce((a, b) => a + b, 0) + const lastResponseTimeAvrg = (sumResponseTime / stats.times[time].length) || 0 + if (stats.responseTimeAvrg > 0) stats.responseTimeAvrg = Math.round((stats.responseTimeAvrg + lastResponseTimeAvrg) / 2) + else stats.responseTimeAvrg = lastResponseTimeAvrg + + console.log('response time avrg total:', stats.responseTimeAvrg) + + rtOP.set(stats.responseTimeAvrg) + + // db.Stats.create({ + // rps, + // responseTime: lastResponseTimeAvrg, + // date: new Date() + // }) + + delete stats.times[time] + } +}, 1000) + +// setInterval(async () => { +// const usersCount = await db.User.count({ +// updatedAt: { +// $gte: new Date(Date.now() - 24 * 60 * 60 * 1000) +// } +// }) + +// usersCountIO.set(usersCount) +// }, 60 * 1000) + +module.exports = async (ctx, next) => { + const startMs = new Date() + + return next().then(() => { + const now = Math.floor(new Date() / 1000) + + if (!stats.times[now]) stats.times[now] = [] + stats.times[now].push(new Date() - startMs) + }) +} \ No newline at end of file diff --git a/utils/weaponShopUpdate.js b/utils/weaponShopUpdate.js new file mode 100644 index 0000000..28bba3d --- /dev/null +++ b/utils/weaponShopUpdate.js @@ -0,0 +1,28 @@ +const rand = require('./rand') +const { + weaponshop, + weapons, + equipment, +} = require('/workspace/degradin/Dev/Telegram/CampFire Play Dev/config') +const fs = require('fs'); + +module.exports = () => { + let weaponId = [] + let equipId = [] + let drop = 1 + let counter = 5 + for (i = 0; i < 5; i++) { + drop = weaponId.push(rand(1, 10)) + } + for (i = 0; i < 5; i++) { + drop = equipId.push(rand(1, 10)) + } + for (i = 0; i < 5; i++) { + weaponshop[i] = weapons[weaponId[i]] + } + for (i = 0; i < 5; i++) { + weaponshop[counter] = equipment[equipId[i]] + counter++ + } + fs.writeFileSync('json/weaponshop.json', JSON.stringify(weaponshop, null, "\t")) +} \ No newline at end of file