#概要
自分でLINE botを作成した際、C#+AWS(Lambda)環境で実装してみたのですが、
この技術スタックでの情報が全く見つかりませんでした。
(自分の探し方が悪かっただけかもしれませんが…)
そこで、今後C#+AWS(Lambda)で作成したい!という方のために手順をまとめておきます。
本記事では、LINEから送信された文字をオウム返しするbotが作成できます。
このベースさえ作ってしまえば、LINE公式ドキュメントを参考に色々いじって楽しめると思います!
内容としては、LINE Developers登録からLambda関数のプログラミング、AWSへのデプロイから最終的に実際にLINEで確認するところまでやってしまいます。
※AWS Lambdaへのデプロイは、Windowsの場合、Visual Studioを使用すればGUIポチポチで完了するので簡単ですが、
Visual Studio for Macの場合はそうはいかないので、
今回はどの環境でも対応できるようCUIからデプロイする操作を記載しております。
#事前準備編(LINE Developers登録)
###LINE Developers登録及びチャンネル作成
LINE botを作成するにあたり、「LINE Developers」に登録する必要があります。
手順は簡単で、申請待ち時間も無いので数分で登録可能です。
下記サイトを参考に、アカウントの作成及びチャンネルの作成まで行います。
※1アカウントで「チャンネル」を複数作成することが可能で、「チャンネル」ごとに別のbotを作成できます。
###チャンネルアクセストークンの発行
LINE botを作成するにあたり、最低限「チャンネルアクセストークン」は発行する必要があります。
チャンネルの作成まで完了したら、Line Develpersにログインし、作成したチャンネルのページにアクセスします。
「Messagin API設定」タブをクリックします。
ページ下部までスクロースし、「チャネルアクセストークン」の発行ボタンをクリックします。
発行されたキーは後ほど使用するのでどこかにメモをしておいて下さい。
※後ほど再度このページにアクセスして発行済のキーを確認することは可能です。
#プログラミング編
無事アクセストークンの発行が完了したら、続いてプログラミングを行っていきます。
C#でのLambda関数プログラミングは、Windowsの場合はVisual Studioを使用すればあらかじめテンプレートが用意されているので簡単ですが、
Visual Studio for Macには用意されていないため、gitにテンプレートを用意しておきました。
※AWSへデプロイするための設定ファイル等も同梱してあります。
ローカルにプロジェクトの準備が完了したら、「Function.cs」ファイルを開きます。
この中の「FunctionHandler()」メソッドがLambda実行時に呼び出されるメソッドです。
つまり、LINEのMessagingAPIからWebhookで呼び出されることになります。
今回はサンプルでbot利用ユーザが入力された文章をそのままオウム返しするようにしてみます。
●LINEからLambdaへのリクエスト内容をモデリング
using System.Collections.Generic;
using Newtonsoft.Json;
namespace LambdaSample.Models
{
public class WebHookRequestModel
{
[JsonProperty("events")]
public List<EventModel> EventModels { get; set; }
}
}
using Newtonsoft.Json;
namespace LambdaSample.Models
{
public class EventModel
{
[JsonProperty("message")]
public MessageModel Message { get; set; }
[JsonProperty("replyToken")]
public string ReplyToken { get; set; }
}
}
using Newtonsoft.Json;
namespace LambdaSample.Models
{
public class MessageModel
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
}
}
●LambdaからLINEへのリプライモデル
using System.Collections.Generic;
using Newtonsoft.Json;
namespace LambdaSample.Models
{
public class ReplyRequestModel
{
[JsonProperty("replyToken")]
public string ReplyToken { get; set; }
[JsonProperty("messages")]
public List<MessageModel> Messages { get; set; }
/// <summary>
/// true: ユーザに通知されない(デフォルト)
/// false: ユーザに通知される
/// </summary>
[JsonProperty("notificationDisabled")]
public bool NotificationDisabled { get; set; }
}
}
●メインの処理
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using BasicExtension;
using LambdaSample.Models;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace LambdaSample
{
public class Function
{
public Function()
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",
Environment.GetEnvironmentVariable("CHANNEL_ACCESS_TOKEN"));
}
public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest input, ILambdaContext context)
{
WebHookRequestModel webHookRequestModel = input.Body.ToObject<WebHookRequestModel>();
string replyToken = webHookRequestModel.EventModels[0].ReplyToken;
MessageModel message = webHookRequestModel.EventModels[0].Message;
ReplyToLine(replyToken, message.Text);
return CreateLambdaApiResponse();
}
private void ReplyToLine(string replyToken, string inputText)
{
string stringRequest = CreateReplyRequestModel(replyToken, inputText).ToJson();
StringContent stringContent = new StringContent(stringRequest, Encoding.UTF8, "application/json");
_httpClient.PostAsync("https://api.line.me/v2/bot/message/reply", stringContent).Wait();
}
private ReplyRequestModel CreateReplyRequestModel(string replyToken, string inputText)
{
ReplyRequestModel replyRequestModel = new ReplyRequestModel();
replyRequestModel.ReplyToken = replyToken;
replyRequestModel.Messages = new List<MessageModel>()
{
new MessageModel()
{
Type = "text",
Text = inputText
}
};
replyRequestModel.NotificationDisabled = false;
return replyRequestModel;
}
private APIGatewayProxyResponse CreateLambdaApiResponse()
{
return new APIGatewayProxyResponse
{
StatusCode = 200,
Body = null,
IsBase64Encoded = false,
Headers = new Dictionary<string, string>() { { "Content-Type", "application/json" } }
};
}
private readonly HttpClient _httpClient;
}
}
#AWSへデプロイ
こちらの記事をご参考下さい。
https://qiita.com/ryohei0109_develop/items/ff05cfad2cb276af1169
今回の例ではjsonファイルはこのようになります。
※「function-role」だけはどうしても書き換えて下さい!
{
"Information": [
"This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
"To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
"dotnet lambda help",
"All the command line options for the Lambda command can be specified in this file."
],
"configuration": "Release",
"framework": "netcoreapp3.1",
"profile": "default", // AWS CLI プロフィール
"region": "ap-northeast-1", // AWSリージョン指定
"function-runtime": "dotnetcore3.1", // Lambbda実行ランタイム
"function-memory-size": 512, // Lambdaメモリ(MB)
"function-timeout": 30, // Lambdaタイムアウト時間(seconds)
"function-handler": "LambdaSample::LambdaSample.Function::FunctionHandler", // Lambda実行時にコールするメソッドを指定
"function-name": "LambdaSample", // Lambda名称
"function-role": "arn:aws:iam::123456789012:role/xxxxxRole" // AWSロール名
}
#Lambda環境変数にチャンネルアクセストークンを設定
チャンネルアクセストークンを環境変数に設定しておくと、今後チャンネルアクセストークンの変更があった際、
プログラムを変更することなくGUIから操作するだけで対応可能になります。
AWSマネジメントコンソールにログイン->Lambda->先程デプロイした関数を選択->「設定」タブをクリック。
キーに「CHANNEL_ACCESS_TOKEN」を指定し、
値に先程Line Develpersで発行した「チャネルアクセストークン」を入力し、「保存」ボタンをクリック。
これで環境変数の設定は完了です!
ここで設定した環境変数は、C#側からは以下のような形で参照することができます。
string value = Environment.GetEnvironmentVariable("CHANNEL_ACCESS_TOKEN")
#LambdaをAPI化
Lambda関数を作成しただけでは、まだLINEからのWebhookを受けることができません。
そこで「API Gateway」を行い、先程作成したLambda関数をAPI化します。
AWSのApiGatewayにアクセスし、「APIを作成」ボタンをクリックします。
少し下にスクロールし、「REST API」の「構築」ボタンをクリックします。
任意の「API名」を入力し、「APIの作成」ボタンをクリックします。
APIの大枠が作成できたら、続いてリソースを作成していきます。
任意のリソース名を入力し、「API Gateway CROSを有効にする」にチェックを入れ、「リソースの作成」ボタンをクリックします。
作成したリソースにPOSTメソッドを追加していきます。
「アクション」から「メソッドの作成」をクリックします。
チェックアイコンをクリックすると、POSTメソッドが作成できます。
「Lambdaプロキシ統合の使用」にチェックし、
先程作成したLambda関数名を入力します。(※サジェストしてくれます)
完了したら「保存」ボタンをクリックします。
「Lambda 関数に権限を追加する」というダイアログボックスが表示されるので、
「OK」ボタンをクリックするとPOSTメソッドの作成が完了します。
POSTメソッドの作成が完了したので、続いてデプロイを行います。
「アクション」から「APIのデプロイ」をクリックします。
「デプロイされるステージ」に「新しいステージ」を選択し、
「ステージ名」に任意の名前を入力し、「デプロイ」ボタンをクリックします。
これでAPI化の準備は完了です!
「POST」を選択し、「URLの呼び出し」に表示されているURLがAPIのエンドポイントになるので、メモしておきます。
#自動応答メッセージをOFF
デフォルトの設定では、ユーザがLINEで文章を送ると自動的にメッセージが返信される設定になっています。
今回は作成したbotから返信を行うので、デフォルトの自動応答メッセージ機能をOFFにする必要があります。
LINE Official Account Managerにログインします。
レフトナビの「応答設定」をクリックします。
※ちなみにこの画面でアカウント名やプロフィール画像を変更できます。
・応答モード: 「Bot」
「チャットモード」にすると、Webhookが利用できません。
・あいさつメッセージ: 「オン」or「オフ」
友達登録時の初回自動送信メッセージのON/OFF切り替えになります。
こちらは好みで良いと思います。
・応答メッセージ: 「オフ」
今回は自分で作成したプログラムから応答するので、オフにしておきます。
・Webhook: 「オン」
オンでないとLINE botが作成できないですね!
これでこの画面での設定は完了です。
あともう少しです!がんばりましょう!
#Webhook登録
先程発行したAPIのエンドポイントを、LINE DevelopersにてWebhook URLとして登録します。
LINE Developersにアクセスし、
作成したチャンネルのページにアクセスし、
「Messaging API設定」タブを選択します。
・ページ下部までスクロールし、Webhookの利用をON
・Webhook設定の「編集」をクリックし、先程発行したAPIのURLを登録します。
Webhook URLの設定が完了したら、「検証」ボタンをクリックし、疎通確認を行います。
正常に疎通できている場合は、「成功」と表示されます。
#LINEアプリで最終確認
最後は先程の画面に表示されているQRコードを読み取って友達登録を行い、
LINEアプリからも正常に動作するか確認してみましょう!
以上です!お疲れ様でした!
#蛇足
参考までに今回私が作成したconpassのイベント検索ができるLINE botも紹介させて下さい。
git: https://github.com/ryohei0109-develop/SearchConnpassLineBot