diff --git a/.env.example b/.env.example index 47895b9..befdf10 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ NODE_ENV=development -LOG_LEVEL=trace \ No newline at end of file +LOG_LEVEL=trace +TOKEN= \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..be5a85a --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# remove-keyboard-bot + +## Run bot +1) install NodeJS +2) clone this repo: `git clone https://git.zeldon.ru/zeldon/remove-keyboard-bot.git` +3) cd to dir with bot +4) write `npm i` +5) cp env: `cp .env.example .env` +6) edit `.env` (add token) +7) start in dev mode: `npm run dev` and prod: `npm run build && node dist/index.js` \ No newline at end of file diff --git a/index.ts b/index.ts index 9f3e1aa..ae939bd 100644 --- a/index.ts +++ b/index.ts @@ -1,4 +1,19 @@ +import { env } from "#root/env.js"; +import { removeKeyboardFeature } from "#root/features/remove-keyboard.js"; +import { welcomeFeature } from "#root/features/welcome.js"; import { logger } from "#root/logger.js"; +import { Bot } from "grammy"; -logger.info("Hello!"); -logger.debug("I am a teapot"); \ No newline at end of file +const bot = new Bot(env.TOKEN); + +bot.use(welcomeFeature); +bot.use(removeKeyboardFeature); + +bot.start({ + onStart: ({ username }) => + logger.info({ + msg: "bot running...", + username, + }), + drop_pending_updates: true +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a455233..f5de660 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "minepulse-simple", + "name": "keyboard-remover-bot", "lockfileVersion": 3, "requires": true, "packages": { @@ -7,11 +7,12 @@ "dependencies": { "dotenv": "^16.3.1", "envalid": "^7.3.1", + "grammy": "^1.19.2", "pino": "^8.16.1", "pino-pretty": "^10.2.3" }, "devDependencies": { - "@types/node": "^20.8.10", + "@types/node": "^20.9.0", "rimraf": "^5.0.5", "tsc-watch": "^6.0.4", "tsx": "^3.14.0", @@ -370,6 +371,11 @@ "node": ">=12" } }, + "node_modules/@grammyjs/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@grammyjs/types/-/types-3.3.0.tgz", + "integrity": "sha512-18Qb12jXiIptqZAlboJMvFxNxydLskUjvE5PbU8ergKQlNIr8jRvYoHDm4t/x3qEfpf+FNhGw23lyZfgEE6e/g==" + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -398,9 +404,9 @@ } }, "node_modules/@types/node": { - "version": "20.8.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", - "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -555,6 +561,22 @@ "node": "*" } }, + "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/dotenv": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", @@ -760,6 +782,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/grammy": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/grammy/-/grammy-1.19.2.tgz", + "integrity": "sha512-bvDWesJgLn65MOsWhShVTVG1bSnh6Yo3OtUwoFzTG21CdPt6r8nzPWcuBSzxMDUQyv8I1c0TXH7zIxXFxiH4sw==", + "dependencies": { + "@grammyjs/types": "3.3.0", + "abort-controller": "^3.0.0", + "debug": "^4.3.4", + "node-fetch": "^2.7.0" + }, + "engines": { + "node": "^12.20.0 || >=14.13.1" + } + }, "node_modules/help-me": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", @@ -857,10 +893,13 @@ } }, "node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", + "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, "engines": { "node": "14 || >=16.14" } @@ -899,12 +938,36 @@ "node": ">=16 || 14 >=14.17" } }, + "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/node-cleanup": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", "dev": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/on-exit-leak-free": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", @@ -1175,6 +1238,33 @@ "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, + "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==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1402,6 +1492,11 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/tsc-watch": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.4.tgz", @@ -1469,6 +1564,20 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1579,6 +1688,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } } diff --git a/package.json b/package.json index e7dfd41..b0b543b 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "name": "remove-keyboard-bot", "main": "dist/index.js", "type": "module", "imports": { @@ -10,7 +11,7 @@ "clean": "rimraf dist" }, "devDependencies": { - "@types/node": "^20.8.10", + "@types/node": "^20.9.0", "rimraf": "^5.0.5", "tsc-watch": "^6.0.4", "tsx": "^3.14.0", @@ -19,7 +20,8 @@ "dependencies": { "dotenv": "^16.3.1", "envalid": "^7.3.1", + "grammy": "^1.19.2", "pino": "^8.16.1", "pino-pretty": "^10.2.3" } -} +} \ No newline at end of file diff --git a/src/env.ts b/src/env.ts index cdfff23..09eeb65 100644 --- a/src/env.ts +++ b/src/env.ts @@ -6,4 +6,5 @@ export const env = cleanEnv(process.env, { LOG_LEVEL: str({ choices: ["trace", "debug", "info", "warn", "error", "fatal", "silent"], }), + TOKEN: str() }); diff --git a/src/features/remove-keyboard.ts b/src/features/remove-keyboard.ts new file mode 100644 index 0000000..bc321b7 --- /dev/null +++ b/src/features/remove-keyboard.ts @@ -0,0 +1,14 @@ +import { Composer, Context } from "grammy"; + +const composer = new Composer(); +const feature = composer.chatType(['group', 'supergroup']); + +feature.command('remove', async (ctx) => { + await ctx.reply('keboard removed', { + reply_markup: { remove_keyboard: true } + }); + + ctx.editMessageReplyMarkup(); +}); + +export { composer as removeKeyboardFeature }; \ No newline at end of file diff --git a/src/features/welcome.ts b/src/features/welcome.ts new file mode 100644 index 0000000..720e4df --- /dev/null +++ b/src/features/welcome.ts @@ -0,0 +1,10 @@ +import { Composer, Context } from "grammy"; + +const composer = new Composer(); +const feature = composer.chatType('private'); + +feature.command(['help', 'start'], async (ctx) => { + ctx.reply('Add this bot to chat and type /remove command'); +}); + +export { composer as welcomeFeature }; \ No newline at end of file