Закрыть
npm

Как отправить сообщение через API ВК на Node.js Редактировано: 28.08.2020 в 04:45

Структура статьи

Знакомство с методом messages.send

Если вы уже знакомы с тем, как использовать API ВКонтакте, то скорее всего вы захотели сделать первый шаг в работе с ним. Лично я начал свое погружение в VK API именно с секции сообщений. Сначала это была просто тестовая отправка сообщения.

И так, для того, чтобы отправлять сообщения, в VK API есть метод messages.send

Минимальные параметры для отправки

  • peer_id - ID отправителя: беседа, или человек, или сообщество
  • message - Текст сообщения, если не указан параметр attachment или sticker_id
  • attachment - Массив с прикреплениями (точнее, строка, разделяющая прикрепления через запятую)
  • sticker_id - ID стикера
  • random_id - Случайное число, для предотвращения дубликатов сообщений. Для простоты генерации, привязывайте его к текущей дате

Чтобы обращаться к VK API на Node.js, я всегда использую модуль easyvk. Есть и другие варианты, например, vk-io или node-vk-bot-api. Что использовать, решать вам. Но писать статьи я решил с примерами использования easyvk, так как эта библиотека мне знакома больше, чем любая другая, хотябы потому что я ее автор :)

На сайте-документации модуля написано подробно о том, как его установить и использовать.

Примеры

Чтобы эта и другие мои статьи о VK API не получились как все типичные статьи из интернета, я буду меньше говорить, и больше показывать.

Отправка сообщения от лица пользователя

Чтобы отправить сообщение от лица пользователя, вам понадобится:

  • Токен пользователя
  • Доступ к секции messages

Хотелось бы напомнить, что Messages API официально закрыт для аккаунтов ВКонтакте, но это не значит, что им нельзя пользоваться. В библиотеке easyvk, для получения доступа, авторизация происходит по данным официальных клиентов ВКонтакте (Приложение для Android, например), которые уже имеют доступ к секции Messages API. Вам почти ничего не надо делать для успешной отправки первого сообщения.

Теперь сам пример

const easyvk = require('easyvk') // Подключаем easyvk

easyvk({ /** Авторизуемся */
  username: 'ВАШ_ЛОГИН',
  password: 'ВАШ_ПАРОЛЬ'
}).then(async (vk) => {
  
  /** Отправляем сообщение */
  let response = await vk.call('messages.send', {
    /** Отправляем самому себе */
    peer_id: vk.session.user_id,
    message: "Привет!",
    /** Получаем случайное число с привязкой к дате*/
    random_id: easyvk.randomId()
  })
  
  console.log(response) // Выводим ID отправленного сообщения

})

Если все получилось, вам придет сообщение с текстом Привет!

Отправка сообщения от лица сообщества

Чтобы отправить сообщение от лица сообщества, вам понадобится:

  • Токен сообщества
  • Доступ к секции messages
  • Доступ к диалогку с пользователем, которому хотите отправить сообщение

Как получить токен сообщества самым простым методом, я описал в этой статье

Чтобы получить доступ к диалогу с пользователем, он должен отправить вам любое сообщение

Параметры все те же.

const easyvk = require('easyvk')

easyvk({
  token: 'ВАШ ТОКЕН СООБЩЕСТВА'
}).then(async vk => {
    
  let peerId = 1 // ID получателя

  /** Отправляем сообщение */
  let response = await vk.call('messages.send', {
    peer_id: peerId,
    message: "Привет!",
    /** Получаем случайное число с привязкой к дате*/
    random_id: easyvk.randomId()
  })
  
  console.log(response) // Выводим ID отправленного сообщения
})

Если все получилось, сообщество отправило сообщение с текстом Привет!

Отправка сообщения в беседу

Для отправки сообщения в беседу в параметре peer_id нужно указать число 2000000000 + ID беседы. ID беседы вы можете получить любым удобным способом: через метод messages.getConversations или по ссылке ВКонтакте
https://vk.com/im?sel=c{ID беседы}

const easyvk = require('easyvk') // Подключаем easyvk

easyvk({
  username: 'ВАШ_ЛОГИН',
  password: 'ВАШ_ПАРОЛЬ'
}).then(async vk => {
  
  /** Получаем список бесед */
  let conversations = await vk.call('messages.getConversations')
  conversations = conversations.items.filter(a => 
    a.conversation && a.conversation.peer.type === "chat"
  )
  
  if (conversations.length) {
    let response = await vk.call('messages.send', {
      peer_id: conversations[0].conversation.peer.id,
      message: "Всем привет!"
    })

    console.log(response)
  }

})

Отправка сообщения в беседу от имени сообщества

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

Настройки сообщества

Сервис можно будет найти в меню сообщества

Сервис для приглашений

Пишем код

const easyvk = require('easyvk') // Подключаем easyvk

easyvk({
  token: 'ТОКЕН СООБЩЕСТВА'
}).then(async vk => {
  
  let response = await vk.call('messages.send', {
    /** 
      ID беседы для сообщества.
      Как его получить, читайте ниже
    */
    peer_id: 2000000009,
    message: "Всем привет!"
  })

  console.log(response) // Всегда 0

})

Как отправлять сообщение от имени сообщества после приглашения в беседу

Это мы уже переходим к разработке мини-чат-бота. Но, конечно, это не он.

Сначала включаем Bots LongPoll (пример будет описан на нем, так как его сможет запустить каждый желающий, позже я буду показывать примеры создания чат-ботов с помощью Callback API тоже)

Для этого заходим в настройки сообщества. И включаем все, что касается LongPoll. А именно:

Настройки сообщества (Работа с API, выставляйте новейшую версию API)

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

Включаем событие входящего сообщения

Теперь подключим Bots LongPoll в easyvk. Не забываем, что приглашение - это обычное входящее сообщение.

const easyvk = require('easyvk')

easyvk({
  token: 'ТОКЕН СООБЩЕСТВА',
  reauth: true,
  v: '5.103' // Обязательно используем новейшую версию ВКонтакте
}).then(async vk => {
  
  /** Подключаемся к LongPoll */
  let connection = await vk.bots.longpoll.connect();
  
  /** Выставляем прослушивание сообщений */
  connection.on("message_new", async (msg) => {
    
    /** Проверяем, что это приглашение в беседу */
    if (
      msg.message && 
      msg.message.action && 
      msg.message.action.type === "chat_invite_user" &&

      /** Проверка, что пригласили именно наше сообщество */
      msg.message.action.member_id === -vk.session.group_id) {
  
      /** Отправляем приветственное сообщение */
      let res = await sendHelloMessage(msg.message.peer_id)
      
      console.log(res) // Всегда 0
    }
  })
  
  async function sendHelloMessage (peerId) {
    return vk.call('messages.send', {
      peer_id: peerId,
      random_id: easyvk.randomId(),
      message: "Всем привет!"
    })
  }

})

Теперь сообщество будет кидать всем беседам приветственное сообщение сразу после приглашения.

Отправка стикера

ВКонтакте позволяет отправлять стикеры в сообщениях. Честно говоря, мне доводилось только один раз прибегать к отправке стикера. Это было, когда я писал чат-бота для глобальных бесед. Там надо было как-то реализовать пересылку любого стикера, который бы отправил пользователь. По-моему, у меня не получилось. Точнее, это работало только с бесплатными стикерами. Самое время разобраться в этом вопросе поглубже.

Все тот же messages.send


easyvk({
  username: 'ВАШ_ЛОГИН',
  password: 'ВАШ_ПАРОЛЬ'
}).then(async vk => {

  /** Получаем недавно использованные стикеры */
  let response = await vk.call('messages.getRecentStickers')
  let recentStickers = response.items;
  
  /** Отправляем самому себе стикер */
  await vk.call('messages.send', {
    peer_id: vk.session.user_id,
    sticker_id: recentStickers[0].sticker_id,
    random_id: easyvk.randomId()
  })

})

Если все получилось, то стикер отправился.

Отправка стикера как граффити

Да-да. И такое бывает. Особенно в последнее время. На сколько мне известно, на данный момент ВКонтакте хранит у себя на серверах 19к стикеров (там почти 20). И все они очень разные, прикольные. Некоторые уже нигде не найти. Но они все равно хранятся. Как в общем-то и любая другая информация в ВК. И это если не считать кастомных стикеров, которые люди загружают как граффити. Разберемся, как они это делают.

Граффити - это обычный документ, загруженный как png изображение. В ВК граффити отображается почти также, как стикер. В некоторых местах, разве что, он бывает в разы больше стикера. А значит и загружать мы его будем как документ.

Для примера возьмем вот такой прикольный стикер https://vk.com/sticker/1-5041-352
Тупа я каждый день

Воспользуемся компонентом uploader для загрузки файла.


easyvk({
  username: 'ВАШ_ЛОГИН',
  password: 'ВАШ_ПАРОЛЬ'
}).then(async vk => {

  let {graffiti} = await vk.uploader.upload({
    getUrlMethod: 'docs.getUploadServer', // Метод получения URL
    getUrlParams: {
      type: 'graffiti' // Отправляем как граффити
    },
    file: 'https://vk.com/sticker/1-162-256', // Что загружаем
    isWeb: true, // Просим скачать файл с удаленного сервера
    saveMethod: 'docs.save' // Сохраняем этим методом
  })

  /** Отправляем самому себе */
  await vk.call('messages.send', {
    peer_id: vk.session.user_id,
    attachment: `graffiti${graffiti.owner_id}_${graffiti.id}`,
    random_id: easyvk.randomId()
  })

})

Вот есть еще такие стикосы

Отправка голосового сообщения

Происходит таким же образом, как и отправка любого документа.

Чтобы отправить голосовое сообщене, вам необходимо его записать в формате Ogg Opus (.ogg). Вы можете записать его в любом другом формате, а затем воспользоваться ffmpeg для форматирования его уже в .ogg, но главное, чтобы в итоге у вас получился файл ogg!

ffmpeg -i audio.wav  -acodec libvorbis audio.ogg

Если вам интересна тема работы с аудио и тем, как я сделал наложение эффектов на голосовое сообщение (реверберация, дисторшн и другие), то можете почитать эту статью

А пока что я покажу простейший пример отправки голосового сообщения

const easyvk = require('easyvk')

easyvk({
  username: 'ВАШ_ЛОГИН',
  password: 'ВАШ_ПАРОЛЬ'
}).then(async vk => {
  let peerId = vk.session.user_id
  let fileName = 'file.ogg'
  
  /** Получаем URL для загрузки */
  let {upload_url: uploadUrl} = await vk.call('docs.getMessagesUploadServer', {
    peer_id: peerId,
    type: "audio_message"
  })
  
  /** Загружаем файл */
  let file =  await vk.uploader.uploadFile(uploadUrl, fileName)
  let doc = await vk.post('docs.save', file)

  doc = doc.audio_message;
  
  await vk.call('messages.send', {
    peer_id: peerId,

    /** Прикрепляем файл как обычный документ */
    attachment: `doc${doc.owner_id}_${doc.id}_${doc.access_key}`,
    random_id: easyvk.randomId()
  })

})

Кстати говоря, отправка аудио сообщений работает и для сообществ! Просто используйте access_token сообщества для настройки под вас.

Отправляем изображение

Вообще, есть два варианта отправки изображения.

  • Изображение с жесткого диска
  • Изображение с удаленного сервера (по URL)

Оба способа поддерживаются в easyvk, поэтому я покажу оба варианта загрузки.

Возьмем какую-нибудь забугорную картинку, почему - не знаю. Просто так. Загрузим ее куда-нибудь в личные сообщения.

Panic Kalm memes

Для загрузки файла с другого сервера в easyvk есть метод vk.uploader.uploadFetchedFile()

Для загрузки файла с жесткого диска в easyvk есть метод vk.uploader.uploadFile()

Напишем код

const easyvk = require('easyvk')

easyvk({
  username: 'ВАШ_ЛОГИН',
  password: 'ВАШ_ПАРОЛЬ'
}).then(async vk => {
  let peerId = vk.session.user_id
  let fileName = 'https://i.imgur.com/PXajpyw.jpg'

  /** Локальная картинка */
  let localFileName = './img.png'
  
  /** Получаем URL для загрузки */
  let {upload_url: uploadUrl} = await vk.call('photos.getMessagesUploadServer', {
    peer_id: peerId
  })
  
  /** Загружаем файл (url, file, field - photo, как в документации) */
  let file =  await vk.uploader.uploadFetchedFile(uploadUrl, fileName, 'photo')
  let localFile =  await vk.uploader.uploadFile(uploadUrl, localFileName, 'photo')

  /** Сохряняем оба изображения */
  let photo = await vk.post('photos.saveMessagesPhoto', file)
  let localPhoto = await vk.post('photos.saveMessagesPhoto', localFile)

  photo = photo[0]
  localPhoto = localPhoto[0]


  /** Отправляем сообщение */
  await vk.call('messages.send', {
    peer_id: peerId,

    /** Прикрепляем файл как обычный документ */
    attachment: [
      `photo${photo.owner_id}_${photo.id}_${photo.access_key}`, 
      `photo${localPhoto.owner_id}_${localPhoto.id}_${localPhoto.access_key}`
    ],
    random_id: easyvk.randomId()
  })

})

На этом все! Спасибо, что дочитали до конца. Надеюсь, что эта статья вам хоть чем-то помогла и вы научились чему-то новому :)

Ссылки

Комментарии к статье