Продолжая свои эксперименты с “умным” домом, ради забавы я решил добавить группу в Вк для управления некоторыми его характеристиками. Для данной статьи конкретизируем задачу: попробуем написать на языке с# простого бота, который будет отвечать от имени сообщества в вк, и рассмотрим, как быстро его запустить на arm32 (в моем случае на orange pi zero).



Мысль про деплой
есть и много других вариантов ( к примеру поставить runtime), это один из них

Итак, разложим по полочкам.

Создаем приложение в вк
Вот тут подробная документация
  1. Для создания бота идем сюда
    Нажимаем «создать приложение» и выбираем «Standalone Application».
  2. Теперь переходим в управление и во вкладке Application Id запоминаем его Id. Оно нам дальше пригодится.


Получаем токен для работы с группами
  1. Отправляем запрос, просто вставляя в браузерную строку:
    https://oauth.vk.com/authorize?client_id=YOURAPPID&group_ids=YOURGROUPID6&display=page&scope=messages,wall,manage&response_type=token&v=5.92

    где YOURAPPID — id приложения, что мы нашли в предыдущем спойлере, а YOURGROUPID id — вашего сообщества.
  2. Даем доступ приложению
  3. И получаем такой ответ
    https://oauth.vk.com/blank.html#expires_in=0&access_token_YOURGROUPID=YOURTOKEN

    Где токен будет очень длинной комбинацией латинских букв и цифр


Проще получаем токен
  1. Заходим в увправление сообществом


Настраиваем сообщество для работы с long poll
  1. Идем во вкладку управления нашим сообществом.
  2. Api Usage и в нем LongPoll Api
  3. Event types (события), в них отмечаем нужные, для тестов я бы отметил все.


Переходим к основной части:

Запускаем любимую ide, создаем консольное приложение на net core



Добавляем VkNet

спойлер
К сожалению на вики документация немного устарела. Одна из причин создания этого гайда.
Но есть отличная поддержка здесь.


Авторизуемся при помощи нашего токена:

var api = new VkApi();
api.Authorize(new ApiAuthParams(){AccessToken =MyAppToken }); 

И в бесконечном цикле будем получать обновления

 while (true)
  {
      var s = api.Groups.GetLongPollServer(MyGroupId);
      var poll = api.Groups.GetBotsLongPollHistory(
              new BotsLongPollHistoryParams()
             {Server = s.Server, Ts = s.Ts, Key = s.Key, Wait = 1});
 }

Проверим пришло ли нам что-нибудь

if(poll?.Updates== null) continue;

Для всех полученных данных узнаем, является ли что-либо из этого сообщением, если да, то напечатаем его содержимое

 foreach (var a in poll.Updates)
  {
      if (a.Type == GroupUpdateType.MessageNew)
    {
        Console.WriteLine(a.Message.Body);
      }
   }

И ответим пользователю тем же текстом

 api.Messages.Send(new MessagesSendParams()
{
     UserId = a.Message.UserId,
     Message = a.Message.Body
});


Полученный код
class Program
    {
        public static string MyAppToken =>
            "f6bf5e26*************************************************************";
        public static ulong MyGroupId => 10******;
        static void Main(string[] args)
        {
            var api = new VkApi();
            api.Authorize(new ApiAuthParams(){AccessToken =MyAppToken });    
            
            while (true)
            {
                var s = api.Groups.GetLongPollServer(MyGroupId);
                var poll = api.Groups.GetBotsLongPollHistory(
                                      new BotsLongPollHistoryParams()
                    {Server = s.Server, Ts = s.Ts, Key = s.Key, Wait = 1});               
                if(poll?.Updates== null) continue;
                  foreach (var a in poll.Updates)
                  {
                      if (a.Type == GroupUpdateType.MessageNew)
                      {
                          Console.WriteLine(a.Message.Body);
                          api.Messages.Send(new MessagesSendParams()
                          {
                              UserId = a.Message.UserId,
                              Message = a.Message.Body
                          });
                      }

                  }
                
            }
        }
    }


Соберем полученный код для нашей платы

dotnet publish . -r linux-arm

И утянем на плату нужную директорию



Отправляемся по ssh и запускаем

chmod +x ConsoleApp1
./ConsoleApp1

Результат
Отправляем сообщение



Получаем сообщение в консоли



Получаем ответ



Диалог


Комментарии (9)


  1. DiegoV
    27.11.2018 09:10

    Спасибо, давно хотел себе заказать плату и поднять пару консольных сетевых утилит на ней.

    Только один вопрос, как автоматически запускать приложение сразу после подачи питания на плату или придется постоянно её пинать по SSH?

    Мне кажется, стоит обратить внимание, что при создании консольного приложения стоит указывать именно .Net Core, а не просто .Net Framework, и что это именно принципиальный аспект, иначе ничего под Linux не заведется.


    1. mayorovp
      27.11.2018 09:49
      +1

      Скорее всего заведется, но запускать придется через mono, а не dotnet.


    1. mayorovp
      27.11.2018 09:52
      +1

      Что же до автозапуска — то вот вам пост: Systemd за пять минут


    1. Larymar Автор
      27.11.2018 09:52

      Как и на любом линуксе можно прописать автозапуск
      Но по первой да, по ssh или другим подключениям пинать
      С моно, как бы не хотелось все не так однозначно


      1. DiegoV
        27.11.2018 10:32

        Ну Mono — это не совсем .Net Framework. Это реализация .Net Standart.


        1. mayorovp
          27.11.2018 10:43

          «Это реализация .Net Standart» можно сказать про .NET Core. А Mono — это не просто .Net Standart, Mono изначально делали так чтобы на ней запускалось как можно больше программ под .Net Framework.


        1. Free_ze
          27.11.2018 12:03

          .Net Framework — это тоже реализация .NET Standard, так что противоречия здесь нет.


          1. DiegoV
            27.11.2018 12:46

            Ну таки речь о том и идет что это две разные реализации одного стандарта.


            1. Free_ze
              27.11.2018 12:51

              Я давненько не слежу за судьбой Mono, но он создавался в те времена, когда .NET Standard не существовало, с целью мимикрирвоать именно под .NET Framework. Что теперь уже автоматически означает соответствие .NET Standard.