Бот в Telegram на языке Grammy JS с функцией Пропозиции | Бот обратной связи в Telegram!

Для нужд своего своего канала я создал Telegram бота на grammY JS для получения обратной связи, в этой статье я поэтапно расскажу про создание такого Telegram бота и его функциональность!

Telegram бот на Grammy JSTelegram бот на Grammy JS

1) Первым делом необходимо получить в Telegram токен для работы нашего бота, для этого необходимо:

– Откройте Telegram и найдите @BotFather в поиске.

– Отправьте ему команду /newbot.

– Бот @BotFather предложит выбрать имя и уникальное имя пользователя для вашего бота.

– Получите ключ — токен для управления ботом.

– Теперь ваш бот готов к разработке!

2) Для разработки нам понадобятся node.js и npm. Проверить наличие пакетов в системе можно с помощью следующих команд:

node -v
npm -v

3) Далее откроем в редакторе кода папку, в которой будем создавать проект. Затем в терминале инициализируем его с помощью npm.

npm init -y

4) Теперь необходимо подключить три библиотеки. Сначала основную – grammY JS, а затем две вспомогательные. Библиотека dotenv используется для хранения токена в качестве переменной окружения (env variable), а nodemon – для автоматического перезапуска кода бота после внесения изменений. Все они могут быть установлены одной командой.

npm i grammy dotenv nodemon

5) Код проекта:

Создадим переменные окружения в отдельном файле .env:

BOT_API_KEY=test
ADMIN_ID=test

Теперь открываем index.js (в нем будет наш основной код) и вставляем строки:

require(‘dotenv’).config();
const { Bot, GrammyError, HttpError, Keyboard, InlineKeyboard } = require(‘grammy’);
const fs = require(‘fs’);

// Создание экземпляра бота
const bot = new Bot(process.env.BOT_API_KEY);

// Файл, в котором будут храниться данные о пользователях
const userDataFile = ‘userData.json’;

// Проверяем существование файла userData.json и создаем его, если он не существует
if (!fs.existsSync(userDataFile)) {
fs.writeFileSync(userDataFile, ‘{}’);
}

let userData = JSON.parse(fs.readFileSync(userDataFile));

Настройка команд и кнопок:

// Начнем с команды /start, которая будет вызываться при первом запуске бота.
bot.command(‘start’, async (ctx) => {
if (!userData[ctx.from.id]) {
// Обновляем данные о пользователе при первом запуске
updateUserData(userDataFile, ctx.from.id);
}
const startKeyboard = new Keyboard()
.text(‘🙋‍♂️ Предложка’)
.row()
.text(‘📲 Социальные сети’)
.row()
.text(‘🔥 Промокоды и скидки’)
.row()
await ctx.reply(
‘Привет! Я бот помошник канала Техноманьяк!’,
);
await ctx.reply(‘С чего начнем? Выбирай 👇’, {
reply_markup: startKeyboard,
});
});
// Обработка команды администратора
bot.command(‘admin’, async (ctx) => {
// Проверяем, является ли пользователь администратором
if (isAdmin(ctx.from.id, process.env.ADMIN_ID)) {
// Если пользователь администратор, отправляем статистику использования бота
let totalStarts = 0;
for (const userId in userData) {
totalStarts += userData[userId].timesStarted;
}
await ctx.reply(`Статистика использования бота:\nВсего запусков: ${totalStarts}`);
} else {
await ctx.reply(‘У вас нет прав администратора!’);
}
});

Обработка пользовательских действий:

// Обработчик нажатий на кнопку “Социальные сети”
bot.hears(‘📲 Социальные сети’, async (ctx) => {
const socialKeyboard = createKeyboard(socialNetworks);
suggestionClicked[ctx.from.id] = false;
await ctx.reply(‘Выберите социальную сеть:’, {
reply_markup: socialKeyboard,
});
});

// Обработчик нажатий на кнопку “Промокоды и скидки”
bot.hears(‘🔥 Промокоды и скидки’, async (ctx) => {
const promoKeyboard = createKeyboard(promoCodes);
suggestionClicked[ctx.from.id] = false;
await ctx.reply(‘Выберите категорию промокодов и скидок:’, {
reply_markup: promoKeyboard,
});
});

Обработка предложений от пользователей:

// Обработчик команды “Предложка”
bot.hears(‘🙋‍♂️ Предложка’, async (ctx) => {
suggestionClicked[ctx.from.id] = true;
await ctx.reply(‘Опишите ваше предложение или сообщение, которое вы хотели бы отправить автору бота.’);
});

// Обработчик всех текстовых сообщений
bot.on(‘message’, async (ctx) => {
const authorId = process.env.ADMIN_ID;

if (suggestionClicked[ctx.from.id]) {
// Пересылаем сообщение от пользователя автору бота
if (ctx.message.text) {
await ctx.forwardMessage(authorId, { text: ctx.message.text });
} else if (ctx.message.voice) {
await ctx.forwardMessage(authorId, { voice: ctx.message.voice });
} else if (ctx.message.photo) {
await ctx.forwardMessage(authorId, { photo: ctx.message.photo });
} else if (ctx.message.video) {
await ctx.forwardMessage(authorId, { video: ctx.message.video });
} else {
await ctx.forwardMessage(authorId, ctx.message);
}

await ctx.reply(‘Ваше сообщение успешно отправлено автору бота’);

} else {
await ctx.reply(‘Пожалуйста, сначала нажмите кнопку “Предложка” для отправки сообщения автору канала!’);
}
});

Вынесение вспомогательных функций в отдельный файл:

Создадим файл buttons.js:

// Массив кнопок для каждой социальной сети
const socialNetworks = [
{ name: ‘YouTube’, url: ‘https://www.youtube.com/@tehno.maniak’, type: ‘social’ },
{ name: ‘Telegram’, url: ‘https://t.me/tehnomaniak07’, type: ‘social’ },
{ name: ‘Vk’, url: ‘https://vk.com/public212223166’, type: ‘social’ },
{ name: ‘ДЗЕН’, url: ‘https://dzen.ru/filimonov-blog.ru’, type: ‘social’ },
{ name: ‘TikTok’, url: ‘https://www.tiktok.com/@texno_maniak’, type: ‘social’ },
{ name: ‘X’, url: ‘https://twitter.com/F1L_zZz’, type: ‘social’ },
{ name: ‘Instagram’, url: ‘https://www.instagram.com/tehnomaniak_blog/’, type: ‘social’ },
{ name: ‘Boosty’, url: ‘https://boosty.to/tehnomaniak’, type: ‘social’ },
];

// Массив кнопок для каждой категории промокодов и скидок
const promoCodes = [
{
name: ”,
url: ”,
code: ‘tehnomaniak’,
description: ‘1 месяц в подарок при оплате сервера на 1 год’,
type: ‘promo’
},
{
name: ”,
url: ”,
code: ‘super’,
description: ‘3 месяца в подарок при оплате сервера на 2 года’,
type: ‘promo’
},
{
name: ”,
url: ”,
code: ‘Не нужен, скидка предоставляет при переходе по ссылке’,
description: ‘Скидка 7% на курсы Яндекс Практикум’,
type: ‘promo’
},
];

module.exports = { socialNetworks, promoCodes };

Для вспомогательных функций создадим файл helpers.js:

//Вспомогательные функции

const fs = require(‘fs’);
const { Keyboard } = require(‘grammy’);

// Функция для обновления данных о пользователе
function updateUserData(userDataFile, userId) {
let userData = JSON.parse(fs.readFileSync(userDataFile));
if (!userData[userId]) {
userData[userId] = {
timesStarted: 0,
};
}
userData[userId].timesStarted++;
fs.writeFileSync(userDataFile, JSON.stringify(userData, null, 2));
}

// Функция для проверки, является ли пользователь администратором
function isAdmin(userId, adminId) {
return userId.toString() === adminId;
}

// Функция для создания клавиатуры с кнопками и кнопкой “Назад”
function createKeyboard(buttons) {
const keyboard = new Keyboard();
const buttonCount = buttons.length;

// Вычисляем количество кнопок в каждой колонке
const buttonsPerColumn = Math.ceil(buttonCount / 2);

for (let i = 0; i < buttonsPerColumn; i++) {
// Добавляем кнопку в первую колонку
const index1 = i;
keyboard.text(buttons[index1].name);

// Проверяем, есть ли кнопка для второй колонки
const index2 = i + buttonsPerColumn;
if (index2 < buttonCount) {
// Добавляем кнопку во вторую колонку
keyboard.text(buttons[index2].name);
}

// Переходим на следующую строку
keyboard.row();
}

// Добавляем кнопку “Назад”
keyboard.text(‘Назад ↩️’);

return keyboard;
}

module.exports = { updateUserData, isAdmin, createKeyboard };

Опробовать бота в действии можно по ссылке!

Код проекта целиком доступен у меня на GitHub.

Инструкция как выполнить деплой Telegram бота на сервер, ссылка.

Ролик на YouTube!

Мой Telegram канал.


 

Источник

Читайте также