LoginSignup
4
2

More than 3 years have passed since last update.

C#でSlackへWebSocket接続(RTM) その2 Windows7対応

Posted at

前回は既存のライブラリではWindows7でWebSocketが使えないことで断念した接続処理を自作します。

WebSocket接続にはwebsocket-sharp
sta/websocket-sharp: A C# implementation of the WebSocket protocol client and server
を使います。これならWindows7でも動作します。

Slackは直接ws接続できるわけではなく、まずはトークンを利用したhttp通信でws用のURLを払いだしてもらう必要があります。
なので、wsクライアントだけではなくhttpクライアントも書く必要があります。

C#にはHTTP用クラスがいくつかデフォルトで用意されているのですが、今回はアセンブリが見つからずHttpClientが使えなかったことと、同期的でいいのでWebClientを利用しました。

JSONは標準ライブラリで解析する方法がやや長そうで読めなかったので、前回のSlackAPIを動かすために必要で用意していたJson.NETを使っちゃいます。

using System.Threading;
using System.Threading.Tasks;
using System;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using System.Text;

using System.Collections.Generic;

using System.Net;
using WebSocketSharp;

class AuthedResult {
    public string url { get; set;}
}

class ReceivedResult {
    public string type { get; set;}
    public string subtype { get; set;}
    public string text { get; set;}



    public JArray attachments { get; set;}
    public string channel { get; set;}
    public string user { get; set;}
    public string username { get; set;}
}


class Slack {
    static void Main() {
        try {
            string url = GetWsUrl();
            using (var ws = new WebSocket (url)) {
            bool ConnectedFlag = false;

            ws.OnMessage += (sender, e) => {
                if (!ConnectedFlag) {
                    // おそらくOnMessageイベントでやる処理ではないが、メッセージがきちゃうので弾きついでに。
                    ConnectedFlag = true;
                    if (e.Data !="{\"type\": \"hello\"}") {
                        throw new Exception("ws connection failed: " + e.Data);
                    }
                    Console.WriteLine ("ws connection success");
                    return;
                }

                Console.WriteLine ("OnMessage: " + e.Data);

                ReceivedResult json = JsonConvert.DeserializeObject<ReceivedResult>(e.Data);
                Console.WriteLine ("OnMessage json: " + json.text);
                if (json.type == "error") {
                    throw new Exception("received type:error: " + e.Data);
                }

                // LINQ覚えたら書き直すかも ただ用途によっては適さない気もする

                if (json.attachments == null) {
                    return;
                }

                foreach( JObject attachment in json.attachments) {
                    JArray fields = (JArray)attachment["fields"];
                    foreach (JObject field in fields) {
                        JValue title = (JValue) field["title"];
                        JValue value = (JValue) field["value"];
                        Console.WriteLine(title.Value);
                        Console.WriteLine(value.Value);
                    }
                }
            };
            ws.Connect ();

            Console.ReadKey (true);
            }
        } catch (Exception e) {
            Console.WriteLine (e.Data);

        }
    }

    static string GetWsUrl() {
        using (WebClient client = new WebClient ()) {
            client.QueryString.Add("token", "xoxp-hogehoge");
            string sresult = client.DownloadString("https://slack.com/api/rtm.connect");
            AuthedResult json = JsonConvert.DeserializeObject<AuthedResult>(sresult);

            //Console.WriteLine(sresult);
            //Console.WriteLine(json.url);
            //Console.ReadKey (true);
            return json.url;
        }

    }

}

参考を見るにJSONをデシリアライズするには構造体を宣言しなければならないと思い込み最初に少し作ったんですが、構造を暗黙的に知っている前提でJObjectだけで処理してもOKです。
もちろんちゃんと宣言したほうが親切ですが。

RTMではユーザー名やチャンネル名はIDで来るので、そのままでは扱いづらいです。

これらを表示名に変換するには事前にchannels.listusers.listで事前に対応表を作っておく必要があるかもしれません。

API Methods | Slack

bat
@echo off
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe ^
 /r:"Newtonsoft.Json.dll" ^
 /r:"websocket-sharp.dll" ^
  ws.cs

参考

Real Time Messaging API | Slack

SlackのRTM APIを直接呼ぶときに困ったこと - Qiita

Visual Studio が無い Windows 環境で c# コードをコンパイルする - Qiita

sta/websocket-sharp: A C# implementation of the WebSocket protocol client and server

外部リソースの解放には using ステートメントを使う - Qiita

Json.NET - Newtonsoft

Json.NET (Newtonsoft.Json) の基本的な使い方 | @Subaru

C#/JSON: Newtonsoft.Json の最も簡単な使い方 - C++ ときどき ごはん、わりとてぃーぶれいく☆

Deserialize an Object

C#でWebAPI叩いてJson形式の結果を受け取る処理メモ - Qiita

C# HTTPクライアントまとめ - Qiita

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2