AzureFunctionを使用して定期的にメッセージ送信するだけのLINEBOTを作る。(C#)


背景

どうしても漏らしてはいけない作業を日次で行う必要があるけどどうすればいいか?と友人から相談を受けていたので何とかできないかと考えていたところ、僕たちの生活に深く根ざしているLINEを利用できないかと思い、BOTを作成するに至りました。また筆者はSEとしてWebアプリの開発に携わる仕事をしていますが、業務でAzure等のクラウドサービスを触ることがなく、常日頃から使うタイミングがないか考えていたところでした。

要件

要件は【毎日21時(営業日等の判定は不要)に「その日のタスクが完了しているか?」を通知する】という非常に簡単な内容でした。またAzureFunctionもAzureBot(Botは今回使用しません)も触ったことがない状態ではありましたが、2時間程度で上手く作成できました。
※本投稿内容は2020年8月に作成したものでその後においてportal画面や仕様の変更があり得ますのでご了承ください。

作成手順

0 : 前提

・LINEの個人アカウントを持っていること。
・Azureアカウントを持っていること。(サブスクリプションやリソースグループは既に作られているものとします。)

1 : LINEBOTの作成

LINE Developersにアクセスし、個人IDでログインします。
普段使用しているLINEアカウントのIDとパスワードで問題ないです。
名前とメールアドレスを入力して開発者アカウントを作成してください。

ログイン後は以下の画面より、以下の画面より新規プロバイダーを作成します。
自分の名前や企業名、組織名を入れろとLINEの公式サイトには記載されています。
ここでは「テスト組織」と入れました。

プロバイダーが作成出来たら、MessageAPIを選んでEnterを押下します。

チャネル名やチャネルのアイコンを自由に設定し、規約に同意するにチェックを入れMessageAPIを作成します。一旦ここまででBOTは作成されましたが、まだ確認したい項目が後続の作業で必要になりますのでそのままにしておきます。

3 : AzureFunctionの作成

次に、Azureポータル画面より定期実行するためAzureFunction(関数アプリ)を作成します。
ここではwindows系のタスクスケジューラーやUNIX系のクーロンみたいなものとして利用します。

関数名を適当に決めて入力してください。私はC#で処理を書きたかったこともあり、以下のように設定しました。終わればホスティングの設定に移ってください。

AzureFunction作成時には必ずストレージアカウントの作成とプランの設定が必要になります。
プランについては月額の支払いにも大いに関わってくるので、間違いないように「App Service プラン」の「F1 free」プランに設定します。(★1)プランは「消費量(サーバーレス)」を選択します。また定期実行するためにテンプレート「TimerTrigger」を使用したいのでOSは「Windows」を選びました。ここでの設定が終われば監視の設定をして「確認および作成」ボタン「作成」ボタンの順に押下するとAzureFunctionが作成されデプロイが完了します。

★1 内容に誤りがありました。申し訳ありません。「App Service プラン」の「F1 free」プランではポータルにログインした時しか関数が実行されない(関数アプリの常時接続ができない)ため、プランは「消費量(サーバーレス)」に設定ください。

4 : TimeTriggerテンプレートを作成する

AzureFunctionが作成されると、TimerTriggerテンプレートを使用し定期実行する関数を作ります。
「関数」タブから移動し「+追加」ボタンを押下し「TimerTriggerテンプレート」を利用してください。

ここでは実行頻度とタイミングを決めます。あくまで入力形式はNCRONTAB式になります。
各単位の間に半角スペースを入れていつ実行するかを表します。
詳細はマイクロソフト公式のDocをご確認下さい。
この場合は毎日21時ということで最初の秒と分は0を、時間は21時なので21を、日と月と何曜日か等の指定はないので*を入力します。

{second} {minute} {hour} {day} {month} {day-of-week}
0 0 21 * * *

5 : 各種設定値を定義する。

表題の通りLINEへのアクセスキーをコードから分離する目的や時間の定義を東京に合わせる設定などを入れるため、
設定値を定義していきます。定義は3で作ったAzureFunctionアプリの「設定」-「構成」タブから作成できます。

①時間設定
デフォルトでは別の国のタイムゾーンで21時に実行されるようになっていますので以下を追加します。
■名前:「WEBSITE_TIME_ZONE」
■値:「Tokyo Standard Time」

②LINEBOTチャンネルアクセストークン
1で作成したBOTを指定してメッセージを送信しますので、LINE DevelopersよりLINEBOTのチャンネルアクセストークンを発行し、追加する必要があります。

LINE Developersより1で作成したBOTのMessaging API設定を押下する。

一番右下にある「発行」ボタンを押下する。

発行された文字列を値に設定し追加する。
■名前:「CHANNEL_ACCESS_TOKEN」
■値:LINE Developersで調べた値になります

値の設定が終われば保存ボタンを確実に押します。

6 : C#で送信処理プログラムを作成する

設定値が完了したら、TimeTriggerから実際にコードを書いてどのような処理(どんなメッセージを表示)させるかを決めます。先ほど作成したTimerTrigger1をクリックし、「コードとテスト」タブを押下するとプログラムが入力できるテキストエディタが表示されます。

送信メッセージに日にちや時間を加えたいので以下のようなコードに書き換えます。

AzureFunction.cs
#r "Newtonsoft.Json"

using System;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

public static async void Run(TimerInfo myTimer, ILogger log)
{
    // チャンネルアクセストークンを変数へ格納
    var channelAccessToken = System.Environment.GetEnvironmentVariable("CHANNEL_ACCESS_TOKEN");

    DateTime dt = DateTime.Now;
    var mm = dt.ToString( "MM" ).TrimStart('0');
    var dd = dt.ToString( "dd" ).TrimStart('0');
    var HH = dt.ToString( "HH" ).TrimStart('0');
    //リプライメッセージ作成
    ReplyMessage rm = new ReplyMessage
    {
        messages = new List<Message>()
        {
            new Message(){
                type="text",
                text=mm + "月"+ dd +"日の"+ HH + "時になりました。本日のタスクは完了していますか?"

            }
        }
    };

    // リプライメッセージをシリアライズ
    string json = JsonConvert.SerializeObject(rm, Formatting.Indented);

    // Line Messaging APIへのリクエストを作成する
    var apiUrl = "https://api.line.me/v2/bot/message/broadcast";
    var req = new HttpRequestMessage(HttpMethod.Post, apiUrl);

    // ヘッダーにチャンネルアクセストークンを追加する
    req.Headers.Add(@"Authorization", @"Bearer {" + channelAccessToken + "}");

    // リクエストをJSON形式にシリアライズする
    req.Content = new System.Net.Http.StringContent(json, System.Text.Encoding.UTF8, "application/json");

    // リクエストを送信する
    using (var client = new HttpClient())
    {
        var response = await client.SendAsync(req);
        log.LogInformation($"{response}");
    }
}

public class ReplyMessage
{
    public List<Message> messages { get; set; }
}

public class Message
{
    public string type { get; set; }
    public string text { get; set; }
}

7 : 実際にデバッグ実行してみる。

実際に自分のLINEアカウントにメッセージが送信されるかテストします。
LINE Developersから作成したLINEBOTのQRコードを読み込んで友達になっておきましょう。

先ほどの「コードとテスト」の画面より「テストと実行」を押下し、更に表示されたウィンドウの「実行」ボタンを押します。「202 Accepted」が返ってきていること及びLINEでメッセージが受信されていることが確認できます。
実行時間が16時台でしたので16時とメッセージが出ており設定値やプログラムに問題ないことの確認も取れました。

一応QRコード置いておきます。

以上で簡単な通知BOT作成手順でした。ご指摘やアドバイスございましたら遠慮なく記載ください。