Самый простой гайд по созданию бота для анализа сообщений в Telegram

fayuv8envtjvvy5ugnukde0ylhs.jpeg


Есть Telegram-каналы, которые отслеживают определенные события в мире. А мы следим за их сообщениями, чтобы не упустить ничего важного. Если собирать и анализировать данные вручную, процесс будет отнимать много времени и требовать высокой концентрации от человека. Чтобы решить эту проблему, наш партнер и фронтенд-разработчик Владилен Минин создал Telegram-бота, который автоматизирует процесс и выдает резюме по собранной информации.

В этой статье рассказываем, как с помощью нейросети создать бота, который собирает и обрабатывает информацию из сообщений, и задеплоить его на облачный сервер.

Возможно, эти тексты тоже вас заинтересуют:

→ Введение
→ Авторизация
→ Реализация функционала
→ Пропускаем сообщения через нейросеть
→ Деплой

Введение


В качестве примера рассмотрим бота, который отслеживает перемещение криптовалют:

9e41fba887c896bccdc2a04c614fd4cc.png
/sum — команда обращения к боту, whale_alert_io — ID канала (можно подставить любой), остальной текст — произвольная команда для робота.


nblot_ve1t3hcw5bluwc_-did08.png

Авторизация


Первым делом нужно авторизовать аккаунт, чтобы получить доступ к сообщениям бота. Через бота такой функционал недоступен, поэтому будем использовать библиотеку GramJS.

Заходим на my.telegram.org, открываем API development tools и создаем приложение.

759d88a334f9ec39c7aa190db667cd37.png


В ответе получаем параметры apiId и apiHash. Подставляем данные в код авторизации:

const { TelegramClient } = require('telegram')
const input = require('input')
const { StringSession } = require('telegram/sessions')
const session = new StringSession('')
const apiId = 123 // подставляем данные из Telegram
const apiHash = 'abc' // подставляем данные из Telegram
;(async () => {
  console.log('Loading interactive example...')
  const client = new TelegramClient(session, apiId, apiHash, {
    connectionRetries: 5,
  })
  await client.start({
    phoneNumber: async () => await input.text('Please enter your number: '),
    password: async () => await input.text('Please enter your password: '),
    phoneCode: async () =>
      await input.text('Please enter the code you received: '),
    onError: (err) => console.log(err),
  })
  console.log('You should now be connected.')
  console.log(client.session.save()) // в консоли получим строчку, которую нужно будет сохранить
})()


Консоль попросит номер телефона, пароль и код подтверждения — заполняем данные и получаем строку сессии. Ее нужно сохранить, чтобы не авторизироваться каждый раз.

13a4074d6b0e7016358e12cc924df16f.png


28ec832591c7eccf72453deb29cf466d.png


Запускаем на Node.js функцию node auth, чтобы получить ключ авторизации и продолжить работу с запросами к Telegram.

2b60621185a695ed25043c1aa0001ac6.png


Реализация функционала


Добавим в Telegram-бот функцию поиска непрочитанных сообщений. Для этого инициализируем client с уже сохраненной сессей. После — используем метод getUnreadMessages:

const { TelegramClient } = require('telegram')
const { NewMessage } = require('telegram/events')
const { session, apiId, apiHash} = require('./config')
const client = new TelegramClient(session, apiId, apiHash, {})
async function getUnreadMessages(channelId, limit = 10) {
  const dialogs = await client.getDialogs({}) // получаем все чаты
  const channel = dialogs.find((d) => d.entity.username === channelId) // находим нужный по ID
  if (channel) { // если канал найдет
    const messages = await client.getMessages(channel.entity, { // получаем список сообщений
      // limit: channel.unreadCount, // можем прочесть количество непрочитанных сообщений
      limit, // сколько сообщений получаем
    })
          console.log(messages.map((m) => m.message).join(' ')) // выводим в консоль
  } else {
    console.log('Канал не найден')
  }
}
;(async function run() {
  // const channel = 'whale_alert_io'
  // watchNewMessages(channel) // важно, чтоб метод был до client.connect
  await client.connect()
  await getUnreadMessages(channelId, 10)
})()


Чтобы бот анализировал не только непрочитанные, но и новые сообщения в чатах, можно использовать метод watchNewMessages:

function watchNewMessages(channelId) {
  client.addEventHandler((event) => {
    console.log('new message', event.message.message)
  }, new NewMessage({ fromUsers: [channelId] }))
}


Пропускаем сообщения через нейросеть


Мы будем использовать GPT-модель GigaChat, которая предоставляет бесплатно до 1 млн токенов. Чтобы начать работу с API, нужно узнать значения ClientID и ClientSecret.

Для этого регистрируемся на сайте GigaChat API и создаем проект. Значение Client ID просто копируем из соответствующего поля в панели справа.

8849f716315c637dc6a27bb65e47727e.png


Поле Client ID. Источник.

И нажимаем Получить Client Secret, чтобы сгенерировать новый секрет.

fcc51d62ea6a1fb141889e6a0018c316.png


Окно с Client Secret. Источник.

Алгоритм работы модели простой. Сначала отправляем запрос на получение токена. Затем делаем запрос к чату с имеющимся токенов. Ниже — пример, как реализован функционал в нашем боте:

const { gigaAuth } = require('./config')
const { v4: uuidv4 } = require('uuid')
const axios = require('axios')
const qs = require('qs')

// метод для получение токена
async function getToken() {
// конфиг запроса
  const config = {
    method: 'post',
    maxBodyLength: Infinity,
    url: '',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      Accept: 'application/json',
      RqUID: uuidv4(),
      Authorization: `Basic ${gigaAuth}`,
    },
    data: qs.stringify({
      scope: 'GIGACHAT_API_PERS'
    }),
  }

  try {
    const response = await axios(config)
    const { access_token: accessToken, expires_at: expiresAt } = response.data

    return { accessToken, expiresAt }
  } catch (error) {
    console.log(error)
  }
}

// выполняем запрос к модели уже с токеном
async function giga(content = '', system = '') {
  if (!content) return

  // получаем токен
  const token = await getToken()

  const messages = []

	// если передавали контекст, то добавляем его как системное сообщение.
  // здесь мы говорим как чату себя вести
  if (system) {
    messages.push({ role: 'system', content: system })
  }

	// формируем данные для обращения
  const data = JSON.stringify({
    model: 'GigaChat',
    messages: messages.concat([
      {
        role: 'user',
        content,
      },
    ]),
    temperature: 1,
    top_p: 0.1,
    n: 1,
    stream: false,
    max_tokens: 512,
    repetition_penalty: 1,
    update_interval: 0,
  })

	// настраиваем запрос
  const config = {
    method: 'post',
    maxBodyLength: Infinity,
    url: '',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
      Authorization: `Bearer ${token.accessToken}`,
    },
    data,
  }

	// выполняем запрос возвращая ответ самого чата
  try {
    const response = await axios(config)
    const message = response.data.choices[0].message
    return message.content
  } catch (e) {
    console.log(e)
  }
}

module.exports = { giga }


Устанавливаем Telegraf, чтобы добавить интерфейс программы в Telegram-бот:

npm i telegraf


Далее получаем токен для @BotFather и создаем Telegram-бот. Вот пример финального файла функционала:

const { TelegramClient } = require('telegram')
const { Telegraf } = require('telegraf')
const { NewMessage } = require('telegram/events')
const { session, apiId, apiHash, botToken } = require('./config')
const { giga } = require('./giga')

создаем бота

const bot = new Telegraf(botToken) const client = new TelegramClient(session, apiId, apiHash) async function getUnreadMessages(channelId, limit = 10) { const dialogs = await client.getDialogs({}) const channel = dialogs.find((d) => d.entity.username === channelId) if (channel) { const messages = await client.getMessages(channel.entity, { limit, }) return messages.map((m) => m.message).join(' ') } else { console.log('Канал не найден') } } ;(async function run() { await client.connect() // слушаем команду sum bot.command('sum', async (ctx) => { // получаем как параметры ID-канала и сообщение для GPT const [, channelId, ...task] = ctx.message.text.split(' ') if (!channelId) { return ctx.reply(`Вы не указали канал`) } // получаем строку из сообщений в канале const messagesString = await getUnreadMessages(channelId, 10) // передаем роль и сообщения из канала в GigaChat const gigaResponse = await giga(messagesString, task.join(' ')) // отправляем пользователю ответ от GigaChat с анализом await ctx.reply(gigaResponse) }) bot.launch() })()


Деплой


Чтобы Telegram-бот был всегда под рукой, задеплоим его в облако Selectel. Для этого переносим шаблон кода в Git:

git init
git add .
git commit -m "init”
git push -u origin master


Далее заходим в панель управления Selectel. Переходим из Облачной платформы в Серверы и нажимаем Создать сервер.

535c336fbc0770b6b65cf20333e58caf.png


Далее настраиваем параметры сервера.

  • Источник: Ubuntu 22.04 LTS 64-bit;
  • Конфигурация: фиксированная, Shared;
  • Доля vCPU: 20% (4 vCPU, 8 ГБ RAM).


975c8ad2a9a9f6082074d13586a100f1.png


После инициализации сервера нужно его настроить. Устанавливаем Git и загружаем репозиторий.

apt update
apt install git
git clone REPO_NAME


После устанавливаем Node.js и NPM через NVM. Подробнее об этом рассказывали в Академии.

Чтобы запустить программу, устанавливаем Node.js на Ubuntu 20.04:

nvm install 20
nvm use 20
cd REPO_NAME
npm install


Далее устанавливаем PM2 для работы бота в фоновом режиме:

npm install pm2 -g
pm2 start main


Готово. Теперь бот работает и вы можете анализировать Telegram-каналы и переписки!

489464d2311c50b039f6c03b3b075c22.png
Больше контента от Владилена Минина вы найдете на его YouTube-канале.

© Habrahabr.ru