伝説のどいつまの伝説~失敗編~

岩美に永住したい新米エンジニアのあれやこれやな話。

【C#】【Bot】Slack Bot で推したちと会話したい!Part.1

事の発端は10月の頭。
とある人より、こんな言葉をもらいました。
「ブログ見たけどさ、やるならもっと面白いことやろーよ!」(意訳)
と……。
求められている面白さがどういうものなのかは分かり兼ねますが、自分で色々調べて何か成し遂げろってことなのかな?と思い、今回こんなネタに挑戦しようと思いました。
会社のメンターに少し相談して、Slack Bot 作るのならば私の今のレベルでもできるんじゃないかということで初の Bot 作りに挑戦です。

どうせなら!!!
大好きな推したちと!!!
会話をしたい!!!よねぇ!!!
という欲にまみれた目標を立てました。
そして一人のオタクは果て無き荒野に一歩踏み出すのだった……。




目標

1. Bot を5つ作る

推し1人だけだと物足りないので、推しと仲の良いキャラも複数作る。

2. 各キャラと、ある程度の会話をできるようにする

それぞれのキャラと1:1で会話をできるようにしたい。
といっても、機械学習まで手をつけると収拾がつかないので、一旦は特定の言葉に対してのレスポンスのみで。

3. Channelの中で会話できるようにする

ひとまずここが最終ゴール。専用のChannelを作ってその中でキャラたち同士で会話をさせたい。


キャラ作成

Slack Bot を作成

まずは、Slack で Bot の基本を作成していきます。
参考 : Slack APIの使い方メモ
Slack API ページから Bot を作成します。 [Create New App] より作成できます。
f:id:d01tsumath:20191013221544p:plain


権限の設定

ここから各 App に対して権限を設定していきます。
[Basic Information] > [Add features and functionality] > [Permissions] > [Scopes] に移動します。
今回設定した権限は、
・Send messages as [App 名] (アプリとしての投稿権限)
・Send messages as user (ユーザーとしての投稿権限)
・Upload and modify files as user (ユーザーとしてのファイルのアップロード権限)
の3つです。 最後のファイルのアップロード権限はいらない気もしますが...一応。
[OAuth Token & Redirect URLs] > [Install App to Workspace] でアプリをインストールします。
すると、Slack のページで App のところにインストールされたことが確認できます。
f:id:d01tsumath:20191013223105p:plain


Incoming Webhook の設定

設定というほどでもないですが、今回は簡単にするために Slack の Incoming Webhook 経由で投稿します。
[Incoming Webhook] > [Activate Incoming Webhooks] を [ON] にします。


API の作成

Azure Functions で簡単作成

Azure Functions で作成します。
まずはきちんと投稿できるか確かめるために簡単なテストコードを書きました。
参考 : Azure Functions(C#)でSlackに投稿する

using System;
using System.Net;
using System.Text;
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 SlackBotTest
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async ValueTask<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest request,
            ILogger log)
        {
            const string WEBHOOK_URL = "https://hooks.slack.com/services/xxxx/xxxx/xxxxx"; // Incoming Webhook で発行されたUrl
            var uri = new Uri(WEBHOOK_URL);
            var wc = new WebClient();

            var slack_text = "俺はフリーしか泳がない";

            var data = JsonConvert.SerializeObject(new
            {
                text = slack_text,
            });

            log.LogTrace("json=" + data);
            wc.Headers.Add(HttpRequestHeader.ContentType, "application/json;charset=UTF-8");
            wc.Encoding = Encoding.UTF8;
            wc.UploadStringAsync(uri, data);

            return new AcceptedResult();
        }
    }
}


WebClient はこのご時世イケてないらしいので、HttpClient で書き直したものがこちら。

using System;
using System.Net.Http;
using System.Text;
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 SlackBotTest
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async ValueTask<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest request,
            ILogger log)
        {
            var slack_text = "俺はフリーしか泳がない";
            const string WEBHOOK_URL = "https://hooks.slack.com/services/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";
            var uri = new Uri(WEBHOOK_URL);

            var data = JsonConvert.SerializeObject(new
            {
                text = slack_text,
            });

            var content = new StringContent(data, Encoding.UTF8, @"application/json");

            var client = new HttpClient();
            var response = await client.PostAsync(uri, content);
            if (response.IsSuccessStatusCode)
                return new AcceptedResult();

            return new BadRequestResult();
        }
    }
}


うまくいくと、このようにSlackに投稿されているのが確認できるかと思います。
f:id:d01tsumath:20191013234455p:plain


本日はここまで。
次回は、会話のバリエーションを増やしたいと思います。