[Из песочницы] Чат-бот для Вконтакте на ASP.NET Core C#

В данной статье представлен пошаговый пример создания простого чат-бота в социальной сети VK на ASP.NET Core C#.


Глава 1. Подготовка

Начнем с создания и настройки сообщества.

s0fm9anijytkpbyvkkmsec0b5xc.jpeg

medfjuaytwryfal4vf66hnmqbum.jpeg

Выбираем любой тип сообщества

pxu21sxtmsa6w0idpkaapcvsnfy.png

Заполняем поля любыми данными и готово! Группа создана.

a_jurxfp1awxwzq1mllau6uyl10.jpeg

Приступим к настройке API

yqndgvo0ufmdp1qysjyyr_-rmiw.jpeg

Создаем API ключ (Разрешаем все)

1j7ov1k9qzuyjxs_bgjhcntxrpc.jpeg

Чтобы реагировать на какие-либо события, наш скрипт должен о них узнать. Для этого существуют два подхода — Callback API и Long Poll. Мы будем реализовывать Callback API.


Немного теории

Callback API — это инструмент для отслеживания активности пользователей в сообществе ВКонтакте. С его помощью можно реализовать, например:


  • Бота для отправки мгновенных ответов на поступающие сообщения.
  • Систему автоматической модерации контента.
  • Сервис для сбора и обработки показателей вовлеченности аудитории.


Настройка Callback API

Выбираем последнюю версию API

gzclnmm9-xsmnsfoqheqqfnnedm.jpeg

Выбираем тип события «входящее сообщение».

nrayuhykowljmjlub9lwfujfq2o.jpeg

Полезная информация:


  1. Знакомство с API ВКонтакте
  2. Callback API VK
  3. JSON-схема


Глава 2. Реализация Callback API

Запускаем любимую IDE, создаем ASP.NET Core Web Application.

Тип проекта: Web Api
Framework: netcoreapp 2.2

sxramuaim2wpwak9sh6wtjdzvge.png

Для подтверждения адреса сервера нам потребуется вернуть строку с уникальным значением.
Берем ее в настройках Callback API.

x27sf_ptdjvw49czhmbqehw8ptm.jpeg

Расширим конфигурацию нашего ASP.NET Core приложения.

Здесь мы будем хранить все ключи, которые будут задействованы в разработке.

5tdz2l8-qa-gbriv4rvxmlmxtfm.jpeg

{
  "Config": {
    "AccessToken": "0bd8573ea40badd694b4da0bbc7d54f52996",
    "Confirmation" : "b23557a3"
  },
  "Logging": {
    "LogLevel": {
    "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Когда в сообществе произойдет событие, ВКонтакте отправит на сервер запрос с данными в формате JSON с основной информацией об объекте, вызвавшем данное событие.


Структура входящего JSON.
{  
   "type":<тип события>,
   "object":<объект, инициировавший событие>,
   "group_id":
}

Например:

{  
   "type":"group_join",
   "object":{  
      "user_id":1,
      "join_type":"approved"
   },
   "group_id":1
}

Для удобства десериализации входящего JSON воспользуемся паттерном Data Transfer Object (DTO).

using System;
using Newtonsoft.Json;

namespace Cookie.Controllers
{
    [Serializable]
    public class Updates
    {
        /// 
        /// Тип события
        /// 
        [JsonProperty("type")]
        public string Type { get; set; }

        /// 
        /// Объект, инициировавший событие
        /// Структура объекта зависит от типа уведомления
        /// 
        [JsonProperty("object")]
        public JObject Object { get; set; }

        /// 
        /// ID сообщества, в котором произошло событие
        /// 
        [JsonProperty("group_id")]
        public long GroupId { get; set; }
    }
}

Для обработки входящих запросом создадим CallbackController.cs.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;

namespace Cookie.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CallbackController : ControllerBase
    {
        /// 
        /// Конфигурация приложения
        /// 
        private readonly IConfiguration _configuration;

        public CallbackController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        [HttpPost]
        public IActionResult Callback([FromBody] Updates updates)
        {
            // Проверяем, что находится в поле "type" 
            switch (updates.Type)
            {
                // Если это уведомление для подтверждения адреса
                case "confirmation":
                        // Отправляем строку для подтверждения 
                    return Ok(_configuration["Config:Confirmation"]);
            }
                // Возвращаем "ok" серверу Callback API
            return Ok("ok");
        }
    }
}


Обратите внимание: после получения уведомления Ваш сервер должен возвращать строку «ok» и статус HTTP 200. Если сервер несколько раз подряд вернет ошибку, Callback API временно перестанет отправлять на него уведомления

Callback API готов!

Полезная информация:


  1. Пример на github
  2. Сериализация и десериализация данных JSON
  3. DI IoC
  4. SDK для .NET Core 2.2


Глава 3. Вк?

Для взаимодействия с VK API на C# воспользуемся библиотекой VkNET

Установка через Nuget:
Package manager:
PM> Install-Package VkNet

.NET CLI:
> dotnet add package VkNet

UI:

kvqtvnj1b-5bhezxsbh7sj0tazk.png

Полезная информация:


  1. Документация VkNET


Глава 4. Больше функционала!

Перед расширением логики бота, авторизуем группу в нашем веб-приложении.
Для этого регистрируем IVkApi в IoC-контейнере.

using VkNet;
using VkNet.Abstractions;
using VkNet.Model;

services.AddSingleton(sp => {
     var api = new VkApi();
     api.Authorize(new ApiAuthParams{ AccessToken = Configuration["Config:AccessToken"] });
     return api;
});

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

Внедряем IVkApi

using VkNet.Abstractions;

private readonly IConfiguration _configuration;

private readonly IVkApi _vkApi;

public CallbackController(IVkApi vkApi, IConfiguration configuration){
     _vkApi = vkApi;
     _configuration = configuration;
}

И сам кейс, который будет ловить новые сообщения. В нем мы добавить немного логики.


Немного документации

RandomId — уникальный (в привязке к API_ID и ID отправителя) идентификатор, предназначенный для предотвращения повторной отправки одинакового сообщения. Сохраняется вместе с сообщением и доступен в истории сообщений.

Заданный RandomId используется для проверки уникальности за всю историю сообщений, поэтому используйте большой диапазон (до int32).

PeerId — идентификатор назначения.

Text — текст личного сообщения. Обязательный параметр, если не задан параметр attachment.

using VkNet.Model;
using VkNet.Model.RequestParams;
using VkNet.Utils;

case "message_new":{
    // Десериализация
    var msg = Message.FromJson(new VkResponse(updates.Object));

    // Отправим в ответ полученный от пользователя текст
   _vkApi.Messages.Send(new MessagesSendParams{ 
       RandomId = new DateTime().Millisecond,
       PeerId = msg.PeerId.Value,
       Message = msg.Text
    });
    break;
}


Глава 5. Деплой

Теперь нам потребуется сервер, куда будут направлены все запросы. Один из бесплатных вариантов это Heroku.

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

tg7af_eo6pyelh8a3xnb3ko3m5s.jpeg

Вводим название проекта.

9z9ahma8wolpzwds91cb9s94brw.png

После создания проекта, будет перенаправление на страницу Deploy

4hbecq54semeatnzidgo018bfr4.png


Для Heroku CLI требуется Git. Если у вас еще не установлен Git, то скачайте его перед установкой CLI.

Для начала скачаем Heroku CLI.

Авторизуем Heroku аккаунт.
$ heroku login

Переходим в проектный каталог.
$ cd (путь до проекта)

Создаём текущем каталоге новый подкаталог с именем .git содержащий все необходимые файлы репозитория — основу Git-репозитория.
$ git init

Подключаемся к удалённому репозиторию (нашему проекту)
$ heroku git:remote -a (название проекта)

Buildpacks отвечают за преобразование развернутого кода в slug, который затем может быть выполнен на dyno.
$ heroku buildpacks:set https://github.com/jincod/dotnetcore-buildpack.git -a (название проекта)

Для того чтобы начать отслеживать (добавить под версионный контроль) наши файлы.
$ git add .

$ git commit -am "cookie"

$ git push heroku master

И идем делать чаёк.

Когда наше приложение будет загружено на Heroku, то мы сможем открыть его по следующей ссылке https://**PROJECT_NAME**.herokuapp.com/

Возвращаемся в нашу группу, и в настройках Callback API указываем ссылку,
обращаяясь к Callback контроллеру.

eewhgaompwf87y8kslmy2-pwb-e.png

Вк отправит JSON запрос на наш сервер, чтобы подтвердить адрес. После ответа будет выведено следующее уведомление: Адрес сервера успешно сохранён

Теперь напишем нашему боту в личные сообщения.

alfmce-sqzrirzzrkpcr6v9trds.png

Удачного кодинга!

© Habrahabr.ru