Moss’s blog

すごくなるためのブログ

LINE BOT C# App without Azure

  • LINE BOT オウム返しがしたいです。
  • ASP.NETを使って。
  • ただし Azureは使わないことを目指します。

やったこと

LINE BOT とやり取りするアプリケーションを作りたい!

  • LINEはみんな使うツール。これに対するサービスが作れれば、うれしいアプリが作れれそう。
  • というか、本当にしたいのは、Raspberry PIと組み合わせて、色々遊びたい。
  • 家をスマートにする。それが目標です。

言語はC#がいい。

  • 自分は、C#を使うので、ASP.NETかな。
  • 前から興味のあった、ASP.NETなので、うってつけ!

Visual Studio用 Template 発見!

  • 以下のページがあり、なんとLINE BOTテンプレートプロジェクトを追加できるということ!先人の偉業をありがたく頂戴します。 pierre3.hatenablog.com

...Azureが必要とな。

  • 説明文を読んでみると、Azureが必要ということ。
  • Azureは使いたくないのです。Azure使うときは、もっとちゃんと使いたいし。。
  • しかし、別のサイト見ても、たいていAzureを使っている。。
  • 一からやっていくしかないのか。。。

そもそもなぜ必要?

  • これから作るアプリはWebアプリ、つまりWebサーバー側で動作するアプリ。
  • Webサーバーをどっかに立てれれば、Azureはいらないのでは?
  • というより、自分のPCがWebサーバーになれば、つまりローカルネットワークの外からアクセスできるようになれば、直接WebHookで要求を受けるけられるようになるのでは?

「ngrok」発見!!

  • 調べると、方法はすぐに出てきた。 ngrok.com
  • Web屋さんは知ってて当然なのだろうかな。
  • まさにやりたいことができるツールで、ローカルアドレスをngrokサービスを介することで、外部からアクセスできるようになるとのこと。これはいい!♬

1つずつ順番に作っていく。

  • 1) LINE BOT作成
  • 2) Webアプリ作成
  • 3) Webアプリを外部に公開
  • 4) 連結

まずは、LINE BOT作成

  • LINE BOTは以下を参照にサクサクと作っていく。 qiita.com
  • 正直、こんなに簡単にBOTが作れるのかと思った。単純なものであれば、プログラム作らなくても事足りる。
  • (LINEを使い始めたころは、胡散臭いサービスだ。ぐらいに思っていたが、気が付けば結構どっぷり使ってしまっている。。)
  • 一つ、つまずいたのは、UIが新しくなっていたため、若干表記が違っていたこと。(ビジネスアカウントも不要でした。プランもFreeでOK。)
  • しかし、まぁ、なんとなくできた。

お次はWebアプリ

  • Webアプリは、一から作れないので、先ほど見つけたLINE BOT Templateから作る。
  • これはAzure上で動作させることを目的としているが、nkrokを使うことで、Azure無しで動作させられる。はず。

LINE Bot Templateの追加

marketplace.visualstudio.com

  • 上記からVSIXがダウンロードできるので、追加する。
  • Visual Studio 2017の「拡張機能と更新プログラム」を開き、LINE BOTを検索してもOK(作成者:pierre3)
  • Visual Studioを閉じると、VSIXインストーラが起動し、機能が追加されます。

ビルド失敗...

  • Visual Studioを起動し、新規作成:「LINEBotApplication」を選択。
  • 生成に成功したので、意気揚々とF7を押下
  • しかし失敗。.NET Frameworkが無いとか言われた。
  • 「まぁ新しのなら大丈夫だろう」とTargetを4.7に変更し、ビルド。
  • とりあえずビルドは通るようになった。

ランタイムエラー: FileLoadException

ファイルまたはアセンブリ 'Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'、またはその依存関係の 1 つが読み込めませんでした。見つかったアセンブリマニフェスト定義はアセンブリ参照に一致しません。 (HRESULT からの例外:0x80131040)

DotNetCompilerPlatformのバージョンを変更

  • よくよくエラー画面を見ると、DotNetCompilerPlatformのバージョンが、実際にVisual Studioで参照設定されているものと違う。
  • これは、WebConfigをもとにロードしている。と予想。
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
    </compilers>
  </system.codedom>
  • 以下へ修正。(Versionを1.0.8.0に変更しました)
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
    </compilers>
  </system.codedom>
  • これで実行。うまく行くかな。。。

FileNotFoundException発生

  • しかし次は、Application_Start()でFileNotFoundExceptionが発生した。
  • 実行まで遠いなぁ...

.NET Framework SDK 4.6.2をインストール

  • 調べたがわからないので、おとなしく、.NET Framework SDK 4.6.2をインストール
  • ついに、ランタイムエラー無く実行成功!

HTTP Error 403.14 - Forbidden が表示される。

f:id:Moss7:20200114002137p:plain
HTTP Error 403.14 - Forbidden

HTTP Error 403.14 - Forbidden Web サーバーは、このディレクトリの内容の一覧を表示しないように構成されています。 - 例外の発生はなくなったが、上記の画面が表示される。 - 何が問題なのか。。。?

いや、、問題ではない!

  • このアプリは別に通常のWEBページを表示するものではないので、問題無いということか。
  • ということで、Webアプリも完成!(として先に進める)

そして、外部へWebアプリを公開!のために「ngrok」をテストする。

  • ngrokをダウンロードし、実行する。
  • アカウントの作成が必要とのことなので、事前に行っておく。 www.jerriepelser.com
  • テスト用にASP.NET Coreテンプレートプロジェクトを作成する。
 dotnet new mvc -o MvcMovie
  • 作成したMvcMovieを起動しておく。
  • デフォルトではhttpsが5001ポート、httpが5000ポートを使用するので、SSLで通信できるようにと、以下のコマンドをコマンドプロンプトから実行
ngrok http 5001

f:id:Moss7:20200113234511p:plain

MvcMovieページが表示されない。

f:id:Moss7:20200113235851p:plain
Bad Gateway 502
- 予定では、「https://d78ff9b3.ngrok.io」にアクセスると、MvcMovieのWelcomページが表示されるはずなのだが。。。 - 「http://localhost:5001」を入力すると表示されるのだか、、、なぜ???
f:id:Moss7:20200114000256p:plain
localhost:5001なら表示される

フォワーディング先が間違っている!

  • ngrokのコンソールをよくよく見ると、存在しないアドレスに対してフォワーディングしている。。
    f:id:Moss7:20200114000604p:plain
    http:\localhost:5001にフォワーディングしている。
  • 5001ポートを使用するのは、httpsで始まるSSL通信のとき。
  • 待っているWebアプリがいないポートに対して表示要求をしていたため、502エラーになっていた模様。

httpsのURLを公開

  • ググると、以下の記事を発見! www.jerriepelser.com
  • なるほど、つまり今回の場合では、以下のコマンドを実行すればいいのか。
ngrok http https://localhost:5001 -host-header="localhost:5001"
  • 実行するとhttpsの5001へフォワーディングするようになった。
    f:id:Moss7:20200114001333p:plain
    https:\localhost:5001へフォワーディング
  • ブラウザからにも表示されるようになった♪ f:id:Moss7:20200114001450p:plain

Conveyorというサービスを発見

www.jerriepelser.com - これを使うと、IPを固定にできるよう。 - ngrokでは、起動するたびにアドレスが変更になるが、これならその心配はない。 - デバッグ用の機能ではあるが、これでもいいのでは?

結局、Conveyorを使用。

  • ngrokを頑張ってやったが、今回はConveyorを使うことにする。(最終的にはラズパイなので、Conveyorは使えないが)
  • やり方は先ほど見つけたページそのまま
  • VSIXは以下のページからダウンロードできる。 marketplace.visualstudio.com

公開完了

  • 咲くほどまで使っていたMvcMovieは終了しておいて、LINE BOT アプリケーションを起動します。
  • Conveyorデバッグ実行中でないと動作しないが、今回はこれで行くことにします。
  • Visual Studioで先ほど作ったLINE Template Applicationを起動する。
  • Conveyorウィンドウが追加されているので、ここで、Access Over Internetをクリックする。
    f:id:Moss7:20200119134827p:plain
    Conveyorウィンドウから公開する
    f:id:Moss7:20200119135248p:plain
    外部からアクセスできるURLが表示される
  • クリックすると、外部からアクセスできるURLが表示されます。
    f:id:Moss7:20200119135248p:plain
    外部からアクセスできるURLが表示される

そして、連結!

  • 連結するには、LINE BOTと、作成したアプリの双方にお互いの情報を設定する必要があります。
  • LINE BOTにアプリの情報(URL)を設定します。(Webhook設定)
  • これにより。LINE BOT -> 自作アプリ ができるようになります。

LINE BOT へ自作アプリ情報を 登録(WebHook設定)

  • LINE Developersから、作成したLINE BOTチャンネルを開き、「Messagein API」を選択。
  • 下のほうにある「Webhook settings」にConveyorウィンドウに表示されていたURLを登録します。

LINE BOT情報の取得

  • 次に自作アプリに登録するために、LINE BOT情報を取得します。
  • LINE BOTの情報「Channel secret 」「Channel access token」が必要になります。

Channel secret

  • LINE Developers > プロバイダーリスト > 管理しているプロバイダー > チャンネル > Basic settings > [Channel secret]

Channel access token

  • LINE Developers > プロバイダーリスト > 管理しているプロバイダー > チャンネル > Basic settings > [Channel access token]

LINE BOT情報の設定

  • 設定方法は、参照している解説ページを見ると、Azureポータルから行うよう。。。
  • しかし!今回は。Azureなしでやりたいのです!
  • Azureに専用の設定ページがあるわけないので、LINE BOT Templateで作成されたファイル内のどこかに設定項目があるはず。。

設定場所はWeb.config

  • 探すとありました。Web.cofigです。
  • 8行目、9行目に、ChannelSecret、ChannelAccessTokenの項目がありました。
  • ここのValueのそれぞれに、LINE Developersページに表示されている文字列を設定すればOK
    f:id:Moss7:20200119141635p:plain
    Web.configへ必要なLINE BOT情報を登録

メッセージを受信しない

  • LINEアプリでLINE BOTを、自身のアカウントから友達登録。
  • そしてメッセージを送ってみる。 しかし、既読スルー。
  • 自作アプリにブレークを張ってみますが、受信していないよう。

WebHookへの指定は、末尾に/api/LINEBOT が必要。

  • 解説ページを見直すと、末尾に/api/LINEBOTをつける必要という説明があり!
  • Azure Function用の解説ページだったので見つけられなかった。 qiita.com
  • LINE DevelopersのWebHook設定の末尾に/api/LINEBOT つけたURLに再設定。

メッセージ受信!しかし応答処理が実行されない。

  • 再度LINE BOTへメッセージを送った。すると受信できた!
  • ブレークを張っていた個所に処理が止まった!
  • しかし!自身のLINEを見ると、依然既読スルー。

Azureが必要な処理があった

  • ステップ実行で処理を追っかけると、Azureに必要な処理が見られた。
  • 写真や動画をAzure上にアップしている?詳しくわからないが、とりあえずコメントアウト
  • 他にも、フォローイベント時に、IDをデータベースに登録していると思われるようなところもあるが、これも気にしないことにする。

Azureが必要な処理をコメントアウト

        [HttpPost]
        public async Task<HttpResponseMessage> Post(HttpRequestMessage request)
        {
            var events = await request.GetWebhookEventsAsync(channelSecret);
            var connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
            //var blobStorage = await BlobStorage.CreateAsync(connectionString, "linebotcontainer");
            //var eventSourceState = await TableStorage<EventSourceState>.CreateAsync(connectionString, "eventsourcestate");

            //var app = new LineBotApp(lineMessagingClient, eventSourceState, blobStorage);
            var app = new LineBotApp(lineMessagingClient, null, null);        // 第2引数、第3引数にnullを指定
            await app.RunAsync(events);

            return Request.CreateResponse(HttpStatusCode.OK);
        }
  • これだと、OnFollowAsync、OnUnfollowAsync、OnLeaveAsync、OnMessageAsync>HandleMediaAsync、の処理が正常に動作しないという問題がある。
  • 今回は無視します。

送受信できた!!!

  • ついに返事が返ってきた!
  • 受信したメッセージの末尾に「モケ」を付加して返信するようにしたため、応答にはちゃんとモケが付いている♪ f:id:Moss7:20200119144519p:plain

長かった。。