【c#】Slackに投稿してスレッドに返信できるようにする。

# 概要

c#からSlackにメッセージを投稿したかったのでやってみました。
`Incoming WebHooks`を使って投稿するなどの記事が多く見かけますがこれだとスレッドに返信できないので。
今回では`chat.postMessage`を使用します。

なぜ今回c#でのSlackに投稿したいかなのですが
`Windowsサービスアプリでリモート接続検知`→`PCが接続した（切断した）`をSlackに投稿したかったからです。
また頻繁に接続するとチャンネルが接続通知であふれかえるのでスレッドに返信できるようにして見た目をすっきりしたい目的もあります。

<b>※2021/0524リモート接続検知してSlackに投稿する記事を書きました。</b>
[【c#】リモートディスクトップ接続を検知してSlackに投稿するWindowsサービスを作成する](https://qiita.com/im0039kp/items/57693925d9695fc25868)

# 開発環境

・Visual Studio 2019
・Slackアプリ(Windowsアプリ版)

# SlackAPIの準備

確認などのために自分のSlackアカウントは作成しておきましょう。
最終的には投稿したいSlackのワークスペースでAPIを作成して運用することになると思います。

### SlackAPIからアプリを作成

[Slack API](https://api.slack.com/apps?new_app=1)からアプリを作成します。

よくサイトの場所を忘れるので私はいつも

・Slackアプリから`設定と管理` > `App管理`からSlackの管理サイトへ行き

|<img width="450" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/60ba6271-00b1-76eb-28cb-0a31042ceb71.png">
:|

・`ビルド`を選択します

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/c5c94de9-b265-47ca-2e6f-2e0a19737926.png">
:|

・`Create New App`から

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/f7c5924a-178e-164c-b014-690993a9f7fb.png">
:|

・今回はゼロからアプリの設定をしていきます。

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/287d8c56-119a-3dbf-ead5-3266ab45820c.png">
:|

|項目|内容|
|:-:|:-:|
|App Name|アプリ名なので好きな名前にする|
|Pick a workspace to develop your app in:|アプリを開発するワークスペースを選択します|
ワークスペースは後で変更できないので注意してください。


|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/9b6a6761-1b5e-c799-08a6-1e079124169b.png">
:|

### 作成したAPIの設定

・Slackの通知でよく見かける`Incoming WebHooks`今回は使いません。

|<img width="450" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/f8b248eb-81f5-0f12-c58e-13e94ff79f0c.png">
:|

・`OAuth&Premissions`から`Scopes`を設定します。

|<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/745d3fdb-15c6-430e-6728-b481a9f9ff0c.png">
:|

・メッセージを投稿したいので`chat:write`に設定します。

|項目|内容|
|:-:|:-:|
|Bot Token Scopes|chat:write|
|User Token Scopes|chat:write|

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/f492280e-f877-678a-4e12-39a6b7ac7a3d.png">
:|

### ワークスペースにインストール

・ここまで設定するとワークスペースにインストールできるようになるのでインストールします。

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/9ac88710-a640-eeed-7c6b-9d36db2a3e24.png">
:|

・リクエスト権限を聞かれた場合は許可しましょう。

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/d811c46e-97a6-6be8-41fa-eae3f8af1a6f.png">
:|

・今回はbotとして投稿したいので`Bot User OAuth Token`の`xoxb-・・・`を使用します。

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/96f37a5f-86fb-efc3-f2a4-0d2bc1cb88e4.png">
:|



### 投稿したいチャンネルにアプリを追加

・`投稿したいチャンネル`に対して`詳細`>`その他`>"アプリを追加する"

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/36d9e5b7-2e62-fe96-5c78-d36167f70a15.png">
:|

・先ほど作成したアプリを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/ad2487d6-45ac-e15c-1924-d6fb42739c84.png)


# Windowsコンソールアプリのプロジェクト作成

・Slackに投稿するための準備はできましたのでWindowsコンソールアプリから投稿してみましょう。
`新しいプロジェクトを作成`を選択して。

|<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/11b9612c-133b-8b5f-1214-d6efc2b31966.png">
:|

・`コンソールアプリ`を選択
(Windowsアプリでもいいですがボタンを作ったり面倒なので簡単な確認ではいつもコンソールアプリを選択しているだけです。)

|<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/a55cfc80-bfc4-c464-8fe1-45b340808c8f.png">
:|

|項目|内容|
|:-:|:-:|
|プロジェクト名|好きな名前|
|場所|好きな保存先にしましょう|

|<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/52d3855c-ade1-863f-b2b5-ec3a7360be26.png">
:|

# 実際に通知コンソールから通知してみる

コンソールアプリで作成したプロジェクトをこのようにします。


```Program.cs
using System.Collections.Specialized;
using System.Net;
using System.Text;
using System.Text.Json;

namespace Prj_SlackMessageBot
{
    class Program
    {
        private static WebClient s_webClient = new WebClient();

        static void Main(string[] args)
        {
            Rootobject rootobject = SendMessageToSlack("Hello World!");
            string ts = rootobject.message.ts;
            SendMessageToSlack("スレッドに投稿", ts);
        }


        public static Rootobject SendMessageToSlack(string text, string thread_ts = "")
        {
            var data = new NameValueCollection();
            data["token"] = "xoxb-・・・"; // Bot User OAuth Token
            data["channel"] = "チャンネル名";// 作成したSlackアプリを追加したチャンネルに(私の場合は#個人)
            data["text"] = text;
            data["thread_ts"] = thread_ts;
            var response = s_webClient.UploadValues("https://slack.com/api/chat.postMessage", "POST", data);
            string responseInString = Encoding.UTF8.GetString(response);
            return JsonSerializer.Deserialize<Rootobject>(responseInString);
        }
    }


}

public class Rootobject
{
    public bool ok { get; set; }
    public string channel { get; set; }
    public string ts { get; set; }
    public Message message { get; set; }
}

public class Message
{
    public string bot_id { get; set; }
    public string type { get; set; }
    public string text { get; set; }
    public string user { get; set; }
    public string ts { get; set; }
    public string team { get; set; }
    public Bot_Profile bot_profile { get; set; }
}

public class Bot_Profile
{
    public string id { get; set; }
    public bool deleted { get; set; }
    public string name { get; set; }
    public int updated { get; set; }
    public string app_id { get; set; }
    public Icons icons { get; set; }
    public string team_id { get; set; }
}

public class Icons
{
    public string image_36 { get; set; }
    public string image_48 { get; set; }
    public string image_72 { get; set; }
}

```

### スレッドに返信するためには

チャンネルに投稿したメッセージの戻り値の`ts`をスレッドに投稿したいメッセージの`thread_ts`に入れることによってスレッドの投稿を可能にしています。

# できたらデバッグしてみましょう。(F5実行)

・デバッグ実行

|<img  alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/3ce34e13-bddc-6af1-420f-faf68c499b06.png">
:|

・無事に投稿できスレッドに投稿もできました。

|<img width="750" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/fa2b464d-9319-6a3d-581c-a180b18bd891.png">
:|


# 小ネタ

### 作成したSlackAPIをウェブ上でテストできます。
[chat.postMessage/test](https://api.slack.com/methods/chat.postMessage/test)


|項目|内容|
|:-:|:-:|
|token|Bot User OAuth Token|
|channel|投稿したいチャンネル|
|text|投稿内容|


|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/fe4ee167-4478-6758-a2f1-35758fccf0ed.png">
:|


### visualstudio上でjsonクラスを自動で生成

・SlackAPIをやり取りするときにjsonで情報が返ってきますがjsonを手動で定義するのが面倒です。
上記のメッセージのテストが成功すると下記のようなjsonが返ってくるのでコピーしてください。

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/1a7cc280-2ff7-858c-9019-01b18bca478c.png">
:|

・貼り付けたい行で`編集`>`形式を選択して貼り付け`>`JSONをクラスとして貼り付ける`と
コードにも書かれているRootobjectクラス以下が自動で生成されます。

|<img alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175167/f1a2226f-e288-89dd-b08d-c35ac8a9c58a.png">
:|

# おわりに

`c#`なので`Unity`などを使ってもよかったですがコンソールアプリで行っています。(最終的にはWindowsサービスを作りたかったので)
SlackのAPIは様々なことができるので他の設定にした場合どのようなことができるのかいろいろ試すといいかもしれません。
次回はリモートデスクトップ接続を検知してこちらで作成したSlackAPIを使ってメッセージを投稿する記事を書ければと思っています。

# 参考

[Slack APIを使用してメッセージを送信する](https://qiita.com/kou_pg_0131/items/56dd81f2f4716ca292ef)
[VisualStudio コピペ JSONをClassとして貼り付けられるtips](https://qiita.com/tsgkdt/items/3e108b2b6c7f2a7e0b21)