From dc03da0a3ed1d3aaf297d084c3300c3f6210df73 Mon Sep 17 00:00:00 2001 From: Ilya Date: Fri, 16 Dec 2022 00:42:34 +0300 Subject: [PATCH] initial --- .gitignore | 2 + .npmrc | 1 + Database.js | 66 +++++++++++++++++++++++++++++++++ index.js | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 20 ++++++++++ scenes/start.js | 55 +++++++++++++++++++++++++++ 6 files changed, 243 insertions(+) create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 Database.js create mode 100644 index.js create mode 100644 package.json create mode 100644 scenes/start.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a1537b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +node_modules diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..e8d4d4f --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=https://repo.redguy.ru/repository/npm-public/ \ No newline at end of file diff --git a/Database.js b/Database.js new file mode 100644 index 0000000..28e9305 --- /dev/null +++ b/Database.js @@ -0,0 +1,66 @@ +const pg = require('pg'); + +class Database { + static instance; + + constructor(connectionStr) { + this.pool = new pg.Pool({connectionString: connectionStr}); + Database.instance = this; + } + + async prepareUser(id) { + let client = await this.pool.connect(); + let user = null; + try { + await client.query('BEGIN'); + let res = await client.query('SELECT * FROM santa_users WHERE id = $1', [id]); + if (res.rowCount === 0) { + await client.query('INSERT INTO santa_users (id) VALUES ($1)', [id]); + res = await client.query('SELECT * FROM santa_users WHERE id = $1', [id]); + } + await client.query('COMMIT'); + user = res.rows[0]; + } finally { + client.release(); + } + return user; + } + + async setGameState(id, state) { + let client = await this.pool.connect(); + try { + await client.query('BEGIN'); + await client.query('UPDATE santa_users SET ingame = $1 WHERE id = $2', [state, id]); + await client.query('COMMIT'); + } finally { + client.release(); + } + } + + async enterGame(id, first_name, last_name, group, problems) { + let client = await this.pool.connect(); + try { + await client.query('BEGIN'); + await client.query('UPDATE santa_users SET first_name = $1, last_name = $2, group_name = $3, problems = $4, ingame = true WHERE id = $5', [first_name, last_name, group, problems, id]); + await client.query('COMMIT'); + } finally { + client.release(); + } + } + + async getUsersCount() { + let client = await this.pool.connect(); + let count = null; + try { + await client.query('BEGIN'); + let res = await client.query('SELECT COUNT(*) as count FROM santa_users WHERE ingame = true'); + await client.query('COMMIT'); + count = res.rows[0].count; + } finally { + client.release(); + } + return count; + } +} + +module.exports = Database; \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..e623011 --- /dev/null +++ b/index.js @@ -0,0 +1,99 @@ +const Telegraf = require('telegraf'); +const session = require('telegraf/session'); +const Database = require('./Database'); +const axios = require("axios"); +const Stage = require("telegraf/stage"); + +let bot = new Telegraf.Telegraf(process.env.TOKEN); +bot.use(session()); +let database = new Database(process.env.DATABASE_URL); + +bot.use(async (ctx, next) => { + let start = new Date(); + ctx.userdata = await database.prepareUser(ctx.from.id); + await next(); + let ms = new Date() - start; + try { + if (ctx.message && ctx.message.text.startsWith("/")) { + let res = await axios.put("https://api.redguy.ru/v1/logs/", { + service: 3, + content: "Command " + ctx.message.text.split(" ")[0].substring(1) + " processed in " + ms + "ms", + level: "info", + category: "Santa" + }, { + headers: { + authorization: "Bearer " + process.env.LOGS_TOKEN + } + }); + console.log(res.data) + } + if (ctx.callbackQuery && ctx.callbackQuery.data) { + await axios.put("https://api.redguy.ru/v1/logs/", { + service: 3, + content: "Callback " + ctx.callbackQuery.data + " processed in " + ms + "ms", + level: "info", + category: "Santa" + }, { + headers: { + authorization: "Bearer " + process.env.LOGS_TOKEN + } + }); + } + } catch (e) { + console.log(e) + } +}); + +let stage = new Stage(); +stage.register(require("./scenes/start")); +bot.use(stage.middleware()); + +bot.start(async (ctx) => { + let keyboard = []; + if(ctx.userdata.ingame) { + keyboard.push([{ + text: "Выйти из игры", + callback_data: "exit" + }]); + } else { + keyboard.push([{ + text: "Войти в игру", + callback_data: "start" + }]); + } + await ctx.reply(`Добро пожаловать в тайного санту студенческого совета ОП5!\n\nТвой статус: ${ctx.userdata.ingame? "В игре" : "Не в игре"}`, Telegraf.Extra.markup((m) => m.inlineKeyboard(keyboard))); +}); + +bot.action("menu", async (ctx) => { + let keyboard = []; + if(ctx.userdata.ingame) { + keyboard.push([{ + text: "Выйти из игры", + callback_data: "exit" + }]); + } else { + keyboard.push([{ + text: "Войти в игру", + callback_data: "start" + }]); + } + await ctx.editMessageText(`Добро пожаловать в тайного санту студенческого совета ОП5!\n\nТвой статус: ${ctx.userdata.ingame? "В игре" : "Не в игре"}`, Telegraf.Extra.markup((m) => m.inlineKeyboard(keyboard))); +}); + +bot.action("start", async (ctx) => { + await ctx.scene.enter("start"); +}); + +bot.action("exit", async (ctx) => { + await database.setGameState(ctx.from.id, false); + await ctx.answerCbQuery("Вы вышли из игры"); + await ctx.editMessageText(`Добро пожаловать в тайного санту студенческого совета ОП5!\n\nТвой статус: Не в игре`, Telegraf.Extra.markup((m) => m.inlineKeyboard([{text: "Войти в игру", callback_data: "start"}]))); +}); + +bot.command("stats", async (ctx) => { + await ctx.reply("Всего игроков: " + (await database.getUsersCount())); +}); + +bot.catch((err, ctx) => console.log(err, ctx)) // Print error and error context to console, no crash + +bot.startPolling(); diff --git a/package.json b/package.json new file mode 100644 index 0000000..8ba1930 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "ks54santa", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^1.2.1", + "pg": "^8.8.0", + "telegraf": "3.39" + }, + "devDependencies": { + "@types/pg": "^8.6.5" + } +} diff --git a/scenes/start.js b/scenes/start.js new file mode 100644 index 0000000..f1f1eda --- /dev/null +++ b/scenes/start.js @@ -0,0 +1,55 @@ +const Scene = require('telegraf').BaseScene; +const Telegraf = require('telegraf'); +const Database = require('../Database'); + +let scene = new Scene('start'); +scene.enter(async (ctx) => { + ctx.session.state = "first_name"; + ctx.session.message_id = ctx.callbackQuery.message.message_id; + ctx.session.chat_id = ctx.callbackQuery.message.chat.id; + await ctx.editMessageText("Введи своё имя", + Telegraf.Extra.markup((m) => m.inlineKeyboard([{text: "Отмена", callback_data: "leave"}]))); + await ctx.answerCbQuery(); +}); + +scene.on('text', async (ctx) => { + switch (ctx.session.state) { + case "first_name": { + ctx.session.first_name = ctx.message.text; + ctx.session.state = "last_name"; + await ctx.telegram.editMessageText(ctx.session.chat_id,ctx.session.message_id, null,"Введи свою фамилию", + Telegraf.Extra.markup((m) => m.inlineKeyboard([{text: "Отмена", callback_data: "leave"}]))); + break; + } + case "last_name": { + ctx.session.last_name = ctx.message.text; + ctx.session.state = "group"; + await ctx.telegram.editMessageText(ctx.session.chat_id,ctx.session.message_id,null,"Введи свою группу", + Telegraf.Extra.markup((m) => m.inlineKeyboard([{text: "Отмена", callback_data: "leave"}]))); + break; + } + case "group": { + ctx.session.group = ctx.message.text; + ctx.session.state = "problems"; + await ctx.telegram.editMessageText(ctx.session.chat_id,ctx.session.message_id,null,"Введи то что тебе нельзя дарить (алергии, запреты родителей и т.д.)", + Telegraf.Extra.markup((m) => m.inlineKeyboard([{text: "Отмена", callback_data: "leave"}]))); + break; + } + case "problems": { + ctx.session.problems = ctx.message.text; + Database.instance.enterGame(ctx.from.id, ctx.session.first_name, ctx.session.last_name, ctx.session.group, ctx.session.problems); + await ctx.telegram.editMessageText(ctx.session.chat_id,ctx.session.message_id,null,"Готово!", + Telegraf.Extra.markup((m) => m.inlineKeyboard([{text: "Меню", callback_data: "menu"}]))); + await ctx.scene.leave(); + } + } + await ctx.deleteMessage(); +}); + +scene.action('leave', async (ctx) => { + await ctx.telegram.editMessageText(ctx.session.chat_id,ctx.session.message_id,null,"Отменено", + Telegraf.Extra.markup((m) => m.inlineKeyboard([{text: "Меню", callback_data: "menu"}]))); + await ctx.scene.leave(); +}); + +module.exports = scene; \ No newline at end of file