ãã³ã¬ã§ãããLINE Clovaéçº ç¬¬4話 Azure Functionsã§ããã¯ãšã³ããäœãã
LINEã®ã¹ããŒãã¹ããŒã«ãŒãLINE Clovaãã¹ãã«éçº ç¬¬4話ã§ã¯ãMicrosoft ã®ãµãŒããŒã¬ã¹ã®ãµãŒãã¹ Azure FunctionsïŒã¢ãžã¥ãŒã« ãã¡ã³ã¯ã·ã§ã³ãºïŒã䜿ã£ãŠããã¯ãšã³ããäœã£ãŠãããŸãïŒïŒã¢ã€ãã£ããã€ã©ã¹ãã»ãã³ã¬ã»è§£èª¬ïŒæ¹å·ããïŒ



â»ããµãŒããŒã¬ã¹ã£ãŠäœïŒããAzure Functionsã£ãŠäœïŒããšããæ¹ã¯ããã³ã¬ã§ãããLINE Clovaéçº ç¬¬1話ãèªãã§ã¿ãŠãïŒ
éçºç°å¢ãçšæããã

Windowsã®å Žå
- Visual Studio Code
- .NET Core 2.1
- Node.js 8.5 以é
- Azure Functions Core Tools
- ngrokïŒããŒã«ã«ã§ Clova ã®ãã¹ããããããã«äœ¿çšïŒ
Azure Functions Core Tools ã¯ãNode.js ãŸã§ã€ã³ã¹ããŒã«ããåŸã次ã®ã³ãã³ãã§ã€ã³ã¹ããŒã«ã§ããŸãã
terminal
$ npm install -g azure-functions-core-tools
macOSã®å Žå
- Visual Studio Code
- .NET Core 2.1
- Homebrew
- Azure Functions Core Tools
- ngrokïŒããŒã«ã«ã§ Clova ã®ãã¹ããããããã«äœ¿çšïŒ
Azure Functions Core Tools ã¯ãHomebrew ãŸã§ã€ã³ã¹ããŒã«ããåŸã次ã®ã³ãã³ãã§ã€ã³ã¹ããŒã«ã§ããŸãã
terminal
$ brew tap azure/functions
$ brew install azure-functions-core-tools
Visual Studio Code ã®èšå®ãããã

- C#
- Azure Functions



Azure Functionsã§ãµããŒããããŠããèšèªã«ã€ããŠã詳ããã¯ãã¡ãïŒ
Azure Functions ã§ãµããŒããããŠããèšèª | Microsoft Docs
Visual Studio Codeã«ãæ¡åŒµæ©èœ C#ã远å


Visual Studio Codeã«ãæ¡åŒµæ©èœ Azure Functionsã远å


ãã³ã©ã ãVisual Studio Codeã®ããããæ¡åŒµæ©èœ

- Paste Image
Ctrl+Alt+V (Cmd+Alt+V) ã§Markdownã«ã¯ãªããããŒãããç»åã貌ãä»ããããšãã§ããæ¡åŒµæ©èœãMarkdownæžãã®ãæããŸãã - VS Live ShareïŒå
¬åŒç޹ä»ãµã€ãïŒ
è€æ°äººãšã³ãŒãå ±æããŠäœæ¥ã§ããããã«ãªãæ¡åŒµæ©èœã§ãã - VS Live Share Extension Pack
Live Share ãããšãã«ããã£ããããã€ã¹ãã£ãããã§ããããã«ãªãæ¡åŒµæ©èœã§ãã - EditorConfig for VS Code
EditorConfig ã®Visual Studio Codeçšã®æ¡åŒµæ©èœã§ããããŒã ã§ã³ãŒãã£ã³ã°ã¹ã¿ã€ã«ãå ±æããã®ã«åœ¹ç«ã¡ãŸãã - GitLens
Git ã®ãªããžããªã®ãã©ã³ãããªã¢ãŒããå±¥æŽãªã©ã確èªããã®ã«äŸ¿å©ã§ãã - GitHub Pull Requests
2019幎1æ22æ¥æç¹ã§ãã¬ãã¥ãŒã§ããVisual Studio CodeããGitHubã®ãã«ãªã¯ãšã¹ããèŠããç·šéãããäœæãããã§ããŠããã䟿å©ã§ãã

ã³ãŒããæžãã
1. æ°èŠãããžã§ã¯ããäœãã
âŒäœæ¥çšã®ãã©ã«ããäœããVisual Studio Codeã§éããŸããç»é¢å·Šã«ããAzureã®ã¢ã€ã³ã³ãã¯ãªãã¯ããŸãã
Sign in to Azureãã¯ãªãã¯ããŠAzureã«ãã°ã€ã³ããŸãã
ïŒç»é¢å·Šã®ã¢ã€ã³ã³ãèŠåœãããªãå Žåã¯ãVisual Studio Codeãåèµ·åããŠã¿ãŠãã ããïŒ

âŒãã©ãŠã¶ãéãã®ã§ãAzureã«ç»é²æžã¿ã®èªåã®ã¡ãŒã«ã¢ãã¬ã¹ãå ¥åããŸãããã®ãããªç»é¢ã«ãªãã°ãã°ã€ã³å®äºã§ãã

âŒFunctionsã®Create New Project... ïŒãã©ã«ãã®ã¢ã€ã³ã³ïŒãã¯ãªãã¯ããŸãã

âŒä»éããŠããäœæ¥çšã®ãã©ã«ããéžæããŸã

âŒç¶ããŠã䜿ãèšèªãéžã³ãŸããä»åã¯C#ãéžæããŸãã

âŒä»¥äžã§ãæ°èŠãããžã§ã¯ããã§ããŸãããå ã»ã©éžæãããã©ã«ãã®äžèº«ãèŠãŠã¿ãŸãããã






2. 颿°ãäœãã
ãããžã§ã¯ããã§ããã®ã§ãç¶ããŠé¢æ°ãäœæããŠãããŸãã

âŒCreate Function ïŒçš²åŠ»ã®ã¢ã€ã³ã³ïŒãã¯ãªãã¯ããŸãã

âŒå ã»ã©äœæãããããžã§ã¯ãã®ãã©ã«ããéžæããŸãã

âŒHttpTrigger ãéžæããŸãã

âŒé¢æ°åãå ¥åããŸããä»åã¯ClovaãšããŸããã

âŒé¢æ°ã®åå空éãå ¥åããŸããä»åã¯MangaClovaãšããŸããã

âŒèªèšŒæ¹æ³ã¯FunctionãéžæããŸãã

âŒæ°ç§åŸãClova.cs ãäœæãããŸãïŒ



3. ã©ã€ãã©ãªã远å ããã
ã³ãŒãã®ç·šéã«å
¥ãåã«ãClova ã® ExtensionïŒã¹ãã«ïŒãäœãããã® CEK.CSharp ãšããã©ã€ãã©ãªã远å ããŠãããŸãããã
C# ã®ã©ã€ãã©ãªã¯ NuGet ã§ãã¹ããããŠããŸãã
ã©ã€ãã©ãªã远å ããã«ã¯dotnet add package ã³ãã³ãã䜿ããŸãã
Visual Studio Code ã®ã¿ãŒããã«ãéããŠã次ã®ã³ãã³ããå ¥åããŸãããã
terminal
$ dotnet add package CEK.CSharp
â» Visual Studio Codeäžã®ã¿ãŒããã«ã®éãæ¹
äžéšã¡ãã¥ãŒã® View ïŒ Terminal ããéããŸãã

詊ãã«ãã«ãããŠã¿ãŸãããã
Ctrl + Shift + B ã§ãã«ãããŸããïŒmacOSã®å Žå㯠â + Shift + BïŒ

ããã«ãã«æåããŸããããšè¡šç€ºããããšã©ãŒãåºãªãããšã確èªããŸãã
4. Clova.cs ã®äžã®Runã¡ãœãããæžãã
Clova.csã®äžã®Runã¡ãœãããæžããŠãããŸãã
å ã ã®ã³ãŒã
C#
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace MangaClova
{
public static class Clova
{
[FunctionName("Clova")]
public static async Task Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
// ããã«å®è¡ãããåŠçãæžã
}
}
}

âŒäŸïŒãŸã using namespace ããŠããªãã¯ã©ã¹ã䜿ããšã
ïŒJavaScript ã§ãããšããã®ãimportããŠããªãã¯ã©ã¹ã䜿ããšã)

â ã¯ã©ã¹åãæã€
â¡ Ctrl + . ãå
¥å
⢠using namespace ã远å ããéžæè¢ãåºãã®ã§éžæ
ã»ã»ã»ïŒãã®äŸã§ã¯ãå
ã»ã©è¿œå ããã©ã€ãã©ãª CEK.CSharp ãåè£ã«è¡šç€ºãããŠããïŒ
⣠ã³ãŒãäžéšã« using namespace; ã远å ããã
ã»ã»ã»ïŒãã®äŸã§ã¯ãusing CEK.CSharp;ïŒ

äœãæ¥ãŠããããã«ã¡ã¯ããè¿ã颿°

C#
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using CEK.CSharp;
using CEK.CSharp.Models;
namespace MangaClova
{
public static class Clova
{
[FunctionName("Clova")]
public static async Task Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
// ãªã¯ãšã¹ãã®ããã£ã® JSON ãæ€èšŒã㊠C# ã®ã¯ã©ã¹ã«å€æã
var clovaClient = new ClovaClient();
var clovaRequest = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);
// è¿äºãäœæ
var clovaResponse = new CEKResponse();
clovaResponse.AddText("ããã«ã¡ã¯ã");
// ã¬ã¹ãã³ã¹ãšããŠäœæããè¿äºã®å
容ãè¿ã
return new OkObjectResult(clovaResponse);
}
}
}
5. ãããã°ãå®è¡
ã³ãŒããå®è¡ããŠã¿ãŸãããã
ç»é¢å·Šã®ã¡ãã¥ãŒãããããã°ãéžæããç·ã®äžè§åœ¢ãã¯ãªãã¯ããŠå®è¡ããŸãã

6. ngrokã䜿ã£ãŠã€ã³ã¿ãŒãããããã¢ã¯ã»ã¹ã§ããããã«ããã
ngrok ã䜿ã£ãŠã€ã³ã¿ãŒãããããã¢ã¯ã»ã¹ã§ããããã«ããŸããVSCode ã®ã¿ãŒããã«ã§æ°ããã¿ãŒããã«ãéããŠã次ã®ã³ãã³ããå®è¡ããŸãã
terminal
$ ngrok http 7071
â» ngrok: command not found ã«ãªã£ãå Žåã»ã»ã»ããŒã«ã«ã§ngrokãåç
§ã§ããŠããªãå¯èœæ§ããããŸããããšãã°ngrokãã¢ããªã±ãŒã·ã§ã³ãã©ã«ãã«ä¿åããå Žå㯠$ cd /Applications ããŠãã $ ./ngrok http 7071 ããŠã¿ãŠãã ããã
æåãããšãã¿ãŒããã«äžã«ãã®ããã«è¡šç€ºãããŸãã

https://b71XXXXX.ngrok.ioãšããURLãããã¯ãã§ããä»ãããã®URLãClova Extension Kitã«ç»é²ããŸãã
ãã©ãŠã¶ã§ Clova Extension Kit ãéããŸããããã¹ãã«ã®åºæ¬æ å ± ïŒ ä¿®æ£ ïŒ ãµãŒãâèšå® ã®ãWebhookã®URLãå ¥ãããšããã« ngrokã§è¡šç€ºãããURL + /api/Clovaãå ¥åããŸãã
äŸïŒhttps://b71XXXXX.ngrok.io/api/Clova

ã§ã¯ãClova Extension Kitã®å¯Ÿè©±ã¢ãã«ã®ãã¹ãæ©èœã§è©±ããããŠã¿ãŸãããã äœã話ããããŠããããã«ã¡ã¯ãããšè¿ã£ãŠããã¯ãã§ãã
âŒãã¹ãããŠã¿ãæ§å




âãã¿ããæ©èœã远å ããã

C#
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using CEK.CSharp;
using CEK.CSharp.Models;
namespace MangaClova
{
public static class Clova
{
[FunctionName("Clova")]
public static async Task Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
// ãªã¯ãšã¹ãã®ããã£ã® JSON ãæ€èšŒã㊠C# ã®ã¯ã©ã¹ã«å€æã
var clovaClient = new ClovaClient();
var clovaRequest = await clovaClient.GetRequest(req.Headers["SignatureCEK"], req.Body);
// è¿äºãäœæ
var clovaResponse = new CEKResponse();
switch (clovaRequest.Request.Type)
{
case RequestType.LaunchRequest:
// èµ·åæã®åŠç
clovaResponse.AddText("ããã«ã¡ã¯ãäœãå ã£ãŠã»ããã§ããïŒ");
clovaResponse.AddText("å¥åº·éãšææéãšééãå ãããã");
clovaResponse.AddText("äŸãã°å¥åº·éãå ã£ãŠã£ãŠèããŠã¿ãŠãã");
clovaResponse.ShouldEndSession = false; // ã¹ãã«ãçµããããªãããã«èšå®ãã
break;
case RequestType.SessionEndedRequest:
// çµäºæã®åŠçãã¹ãã«ãçµäºãããšãã«äœããããæã¯ãããã«åŠçã远å ããŸã
break;
case RequestType.IntentRequest:
// ã€ã³ãã³ãã®åŠç
switch (clovaRequest.Request.Intent.Name)
{
case "FortuneTellingIntent":
// å ãã®ã€ã³ãã³ã
// å ã察象ãã¹ãããã«ç¡ãå Žåã¯ç·åéå¢ãå ã
var fortune = "ç·åéå¢";
if (clovaRequest.Request.Intent.Slots.TryGetValue("FortuneSlot", out var fortuneSlot))
{
// å ãã®å¯Ÿè±¡ãããå Žåã¯ããããã¹ãããããååŸãã
fortune = fortuneSlot.Value;
}
// å ãã®çµæãè¿ã
var result = new[]{ "倧å", "äžå", "å°å", "æ«å" }[new Random().Next(4)];
clovaResponse.AddText($"{fortune} 㯠{result} ã§ãã");
break;
default:
// èªèã§ããªãã£ãã€ã³ãã³ã
clovaResponse.AddText("ããããªãããããããããŸããã§ãããäŸãã°å¥åº·éãå ã£ãŠãšèšããšå¥åº·éãå ããŸãã");
clovaResponse.ShouldEndSession = false; // ã¹ãã«ãçµããããªãããã«èšå®ãã
break;
}
break;
}
// ã¬ã¹ãã³ã¹ãšããŠäœæããè¿äºã®å
容ãè¿ã
return new OkObjectResult(clovaResponse);
}
}
}
ã³ãŒããä¿åããããããã°ãå®è¡ããŠãã ããã ããã§è©±ãããããšãæ¯åéã£ãçµæãè¿ã£ãŠããããã«ãªããŸãã


ãããã€ããã
1. Azureã«ãããã€ããã
ãã¹ãããŠã¿ãŠæ£åžžã«åããã®ã§ãããããæ¬çªç°å¢ã«ãããã€ããŠã¿ãŸãããã
âŒVisual Studio Codeã®å·ŠåŽã«ããAzureã®ã¢ã€ã³ã³ãã¯ãªãã¯ããDeploy to Function App...ïŒäžåãç¢å°ã®ã¢ã€ã³ã³ïŒãã¯ãªãã¯ããŸãã

âŒCreate New Function App ãéžæããŸãã
Function App ã®ååã®å
¥åãæ±ããããŸããURL ã«äœ¿ãããã®ã§äžçäžã§äžæã§ããå¿
èŠããããŸãã䜿ããæåã¯ãa-zã0-9ã- ã§ãã


âŒãªãœãŒã¹ã°ã«ãŒããäœæããŸããCreate new resource group ãéžæããŸãã ãªãœãŒã¹ã°ã«ãŒããšã¯ãAzure äžã®äœæããã¢ããªã DB ãã²ãšãŸãšãã«ããŠç®¡çãããã©ã«ãã®ãããªãã®ã§ãã

âŒãªãœãŒã¹ã°ã«ãŒãåãå ¥åããŸãã

âŒAzure Functions ãå éšã§äœ¿ãã¹ãã¬ãŒãžãäœããŸããCreate new storage account ãéžæããŸãã

âŒã¹ãã¬ãŒãžã¢ã«ãŠã³ãåãå ¥ããŸãããããäžçäžã§äžæã®ååã§ããå¿ èŠããããŸãã

âŒç¶ããŠãªãŒãžã§ã³ãéžæããŸããæ¥æ¬ã¯Japan WestãšJapan EastããããŸãã


âŒãªãŒãžã§ã³ãéžæãããšãããã€ãå§ãŸããŸããç»é¢å³äžã«ãããã¢ããã衚瀺ãããŸãã

âŒåºåãŠã£ã³ããŠïŒOUTPUTãŠã£ã³ããŠïŒã§Azure Functionsãéžæãããšãããã€ã®ç¶æ³ã確èªã§ããŸãã

âŒãããã€ãå®äºãããšVisual Studio Codeã®Azure Functionsæ¡åŒµæ©èœãã颿°ïŒFunctionsïŒã確èªã§ããŸãã

âŒé¢æ°Clovaãå³ã¯ãªãã¯ããŠé¢æ°ã®URLãã³ããŒããŸãã

âŒãã®URLã Clova Extension Kitã® ã¹ãã«ã®åºæ¬æ å ± ïŒ ä¿®æ£ ïŒ ãµãŒãèšå® ã«èšå®ããããšã§ãAzure Functionsã§LINE Clovaã®ã¹ãã«ãåãããã«ãªããŸãïŒ

âŒç¡äºãAzure Functionsãä»ããŠè¿çãè¿ã£ãŠããŸããã

âŒã¡ãªã¿ã«ããã©ãŠã¶ãã AzureããŒã¿ã«ã確èªããŠã¿ããšããããã€ã§ããŠããã®ã確èªã§ããŸãã




â» æ¬èšäºã¯2019幎1æäœææç¹ã§ã®æ å ±ã§ãã
次åã第5話ãžç¶ã
- 第1話ïŒClovaéçºã®å šäœåã»ãµãŒããŒã¬ã¹ã£ãŠäœïŒ
- 第2話ïŒã¹ãã«ã®åºæ¬æ å ±ãç»é²ããã
- 第3話ïŒå¯Ÿè©±ã¢ãã«ãäœãã
- 第4話ïŒããã¯ãšã³ããã€ãããïŒæ¬èšäºïŒãâä»ã³ã³ïŒ
- 第5話ïŒå®æ©ã§åãããŠã¿ãã
- 第6話ïŒå¯©æ»ã«åºããŠå ¬éããŠã¿ãã
- 第7話ïŒClovaã®ã¹ãã«ããã£ãšãªããã«ããŠã¿ãã
ãã³ã¬ã»è§£èª¬ïŒ æ¹å·ãã
ä»ã«ããããããã°ã¡ãããšåŠã¶ãã·ãªãŒãº
ãã³ã¬ãšå³è§£ã§æè¡ãããããããã°ã¡ãããšåŠã¶ãã·ãªãŒãºã
å
šåœã®æžåºã»Amazonã§çºå£²äžã§ãã
èè ãããã£ãŒã«

æ¹å·ãã
çµµãæãWebãã¶ã€ããŒãé«çåŠæ ¡æè«å
èš±ç¶ âæ
å ±ç§â ååŸæžããã³ã¬ãšå³è§£ã®åã§ãç©äºãããããããäŒããããšã奜ãã2014幎ããããã³ã¬ã§ãããWebãã¶ã€ã³ããã€ã³ã¿ãŒãããäžã«å
¬éããŠãããšãããåºç瀟ãã声ããããã
Twitter: @llminatoll
Webãµã€ã: ãã³ã¬ã§ãããWebãã¶ã€ã³

ã¡ããŸã©ïŒå代ç°ãŸã©ãïŒ
ãšã³ãžãã¢å
Œãã³ã¬å®¶ãMicrosoft 瀟ã®ãœãããŠã§ã¢ãšã³ãžãã¢ãšããŠã®æ¬æ¥ã®ããããããã³ã¬å®¶ãã€ã©ã¹ãã¬ãŒã¿ãŒãæŸå±ãšãã³ãžã§ãªã¹ã(éå
¬åŒ)ãšããŠã掻åãMSå
¥ç€Ÿåãã Twitter å»äººã§ããããã©ãã¯ãŒã¯4äžäººãè¶
ããã
Twitter: @chomado
ããŒã ããŒãž: http://chomado.com/
















