Данный репозиторий содержит пример создания скилла для Алисы на языке c# под платформу .net core 2.1
- Для начала необходимо установить
dotnet sdk
- (с официального сайта) идем на https://www.microsoft.com/net/download и скачиваем
2.1 SDK (v2.1.300)
и устанавливаем - brew
- apt-get
- (с официального сайта) идем на https://www.microsoft.com/net/download и скачиваем
- Создаем новый проект
$ dotnet new console -o alice
- добавляем нужные зависимости:
$ dotnet add package Microsoft.AspNetCore
$ dotnet add package Microsoft.AspNetCore.Mvc
- Удаляем файл Program.cs, он нам не нужен и создаем файл
Alice.cs
, в этом файле будет наш контроллер вебхука - Добавляем импорты:
// Alice.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
- Создаем класс
Alice
унаследованный от классаController
это файл будет содержать бутстрапинг сервера и простой ответ
// Alice.cs
public class Alice : Controller {
}
- Добавляем метод
CreateWebHostBuilder
- этот метод создаст объектIWebHostBuilder
, добавит сервисы необходимые дляmvc
и настроит дефолтный роутинг
// Alice.cs
public class Alice : Controller {
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureServices(srv => srv.AddMvc())
.Configure(app => app.UseMvc());
}
- Далее создадим точку входа в наше приложение которое получит объект из пунка 4 и запустит хост
static void Main(string[] args) => CreateWebHostBuilder(args).Build().Run();
- Наш веб сервер готов, запустить можно его просто командой
$ dotnet run
сервер запустится и выведет на экран примерно следующее:
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using '/Users/seralexeev/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
Hosting environment: Production
Content root path: /Users/seralexeev/projects/alice-dotnet
Now listening on: https://localhost:5000
Now listening on: https://localhost:5001
Application started. Press Ctrl+C to shut down.
Наш сервер будет доступен на 5000 и 5001 портах, изменить это поведение можно добавив параметр --urls
$ dotnet run --urls "https://localhost:3000"
Hosting environment: Production
Content root path: /Users/seralexeev/projects/alice-dotnet
Now listening on: https://localhost:3000
Application started. Press Ctrl+C to shut down.
Для взаимодействия с api опишем классы в соответсвии с https://tech.yandex.ru/dialogs/alice/doc/protocol-docpage
// Models.cs
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class SessionModel {
[JsonProperty("new")]
public bool New { get; set; }
[JsonProperty("session_id")]
public string SessionId { get; set; }
[JsonProperty("message_id")]
public int MessageId { get; set; }
[JsonProperty("skill_id")]
public string SkillId { get; set; }
[JsonProperty("user_id")]
public string UserId { get; set; }
}
public class ResponseModel {
[JsonProperty("text")]
public string Text { get; set; }
[JsonProperty("tts")]
public string Tts { get; set; }
[JsonProperty("end_session")]
public bool EndSession { get; set; }
[JsonProperty("buttons")]
public ButtonModel[] Buttons { get; set; }
}
public class ButtonModel {
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("payload")]
public object Payload { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
[JsonProperty("hide")]
public bool Hide { get; set; }
}
public class MetaModel {
[JsonProperty("locale")]
public string Locale { get; set; }
[JsonProperty("timezone")]
public string Timezone { get; set; }
[JsonProperty("client_id")]
public string ClientId { get; set; }
}
public class AliceRequest {
[JsonProperty("meta")]
public MetaModel Meta { get; set; }
[JsonProperty("request")]
public RequestModel Request { get; set; }
[JsonProperty("session")]
public SessionModel Session { get; set; }
[JsonProperty("version")]
public string Version { get; set; }
}
public enum RequestType {
SimpleUtterance,
ButtonPressed
}
public class RequestModel {
[JsonProperty("command")]
public string Command { get; set; }
[JsonProperty("type")]
public RequestType Type { get; set; }
[JsonProperty("original_utterance")]
public string OriginalUtterance { get; set; }
[JsonProperty("payload")]
public JObject Payload { get; set; }
}
public class AliceResponse {
[JsonProperty("response")]
public ResponseModel Response { get; set; }
[JsonProperty("session")]
public SessionModel Session { get; set; }
[JsonProperty("version")]
public string Version { get; set; } = "1.0";
}
и добавим метод расширения для AliceRequest
для простого создания ответа
// Extensions.cs
public static class Extensions {
public static AliceResponse Reply(
this AliceRequest req,
string text,
bool endSession = false,
ButtonModel[] buttons = null) => new AliceResponse {
Response = new ResponseModel {
Text = text,
Tts = text,
EndSession = endSession
},
Session = req.Session
};
}
На последнем шаге необходимо добавить эндпоинт который и зарегистрируем в платформе диалогов
// Alice.cs
public class Alice : Controller {
...
[HttpPost("/alice")]
public AliceResponse WebHook([FromBody] AliceRequest req) => req.Reply("Привет");
...
}
В итоге наш котнтроллер будет выглядить примерно так:
// Alice.cs
public class Alice : Controller {
static void Main(string[] args) => CreateWebHostBuilder(args).Build().Run();
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureServices(srv => srv.AddMvc())
.Configure(app => app.UseMvc());
[HttpPost("/alice")]
public AliceResponse WebHook([FromBody] AliceRequest req) => req.Reply("Привет");
}
$ docker build -t alice .
$ docker run --rm -it -p 5000:80 alice
Для проверки нашего еще неопубликованного скила необходимо зарегистрироваться и создать "Навык в Алисе" на https://dialogs.yandex.ru/developer/
- Для тестирования оффлайн можно использовать юнит тесты или интеграционные тесты, описанные в классе
AliceTests
- Для тестирования через консоль разработчика можно использовать
ngrok
- Запускаем проект в режиме
watch
, dotnet будет следить за изменениями в файлах и перезапускать сервер:dotnet watch -p src run
- Запускаем
ngrok
:ngrok http 5000
- Прописываем сгенерированный адрес в консоль разработчика, в итоге получаем возможность писать код и сразу проверять его во вкладке тестирования в консоле разработчика
- Запускаем проект в режиме