LoginSignup
2
1

More than 3 years have passed since last update.

C#からSlackAPIを利用して、指定期間内に投稿されたメッセージを取得する

Posted at

はじめに

本記事はC#からSlackAPIを利用して、指定期間内に投稿されたメッセージを取得する方法をまとめることを目的としています。
なお、以前に以下のようなSlackAPIに関する記事を投稿していますので、こちらの記事を先に読んでいただくことをお勧めします。

利用するAPIとAPI引数

メッセージを取得するためにはこちらのAPIを使います。
投稿時間を指定するためには以下のoldest, latest引数を設定してAPIを呼び出す必要があります。

image-20200709090717712.png

oldestは取得するメッセージの投稿時間の最小値、latestは取得するメッセージの投稿時間の最大値を表します。つまり、oldestとlatestを両方設定すると、oldest~latest間のメッセージを取得することができます。

oldest, latestの指定方法

こちらの公式文書に書かれているようにSlackでは時間をUNIX時間形式で扱っています。UNIX時間はUNIX系のコンピューターシステムで標準的に使われている時刻表現のことです。詳細はこちらを参照ください。
そのため、例えば2020年7月1日に投稿されたメッセージを取得する場合は、oldest, latestにそれぞれ以下のような値を入れて、APIを呼び出します。

  • oldest
    2020年7月1日 0:00を表現するUNIX時間

  • latest
    2020年7月2日 0:00を表現するUNIX時間

C#でUNIX時間を作り出す方法

C#上でUNIX時間を作り出すには、DateTimeOffset構造体から変換するのが簡単だと思います。
手順としては、以下になります。

  1. DateTime構造体でUNIX時間に変換したい日時情報を作成
  2. 1でつくったDateTime型の値を使って、DateTimeOffset構造体を作成(リファレンスはこちら)
  3. 2のDateTimeOffset型の値をこちらのメソッドでUNIX時間に変換

時間を指定してメッセージを取得するサービス

これまでの内容を活かして、投稿時間を指定してメッセージを取得するサービスを作成します。こちらの記事で作成したメッセージを取得するGetMessagesメソッドを拡張して、実現します。

/// <summary>
/// Slackメッセージの取得に必要な機能を提供するサービス
/// </summary>
public class SlackMessageGetService
{
    #region 定数

    /// <summary>
    /// アクセストークン用のクエリパラメータ名
    /// </summary>
    private const string c_AccessTokenQueryParameterName = "token";

    /// <summary>
    /// チャンネルID用のクエリパラメータ名
    /// </summary>
    private const string c_ChannelIdQueryParameterName = "channel";

    /// <summary>
    /// 取得メッセージ数用のクエリパラメータ名
    /// </summary>
    private const string c_MessageCountQueryParameterName = "limit";

    /// <summary>
    /// 投稿時間の最小値用のクエリパラメータ名
    /// </summary>
    private const string c_OldestQueryParameterName = "oldest";

    /// <summary>
    /// 投稿時間の最大値用のクエリパラメータ名
    /// </summary>
    private const string c_LatestQueryParameterName = "latest";

    ・・・

    #endregion

    #region フィールド

    /// <summary>
    /// SlackにPOST,GETするために使用するHttpClient
    ///
    /// ユーザーの利用方法を想定したとき、接続先のホストは[チーム名].slack.comしかありえないため、
    /// HttpClientは単一インスタンスのみとする
    /// </summary>
    // ReSharper disable once InconsistentNaming
    private static readonly HttpClient m_HttpClient = new HttpClient();

    #endregion

    #region 公開サービス

    /// <summary>
    /// メッセージを取得する
    /// </summary>
    /// <param name="accessToken">アクセストークン</param>
    /// <param name="channelId">チャンネルID</param>
    /// <param name="messageCount">取得するメッセージ数</param>
    /// <param name="oldest">投稿時間の最小値</param>
    /// <param name="latest">投稿時間の最大値</param>
    /// <returns>取得メッセージ一覧</returns>
    public async Task<IEnumerable<Message>> GetMessages(string accessToken, string channelId, int messageCount, DateTime oldest, DateTime latest)
    {
        var messages = new List<Message>();

        // latestとoldestをUNIX時間に変換
        var oldestDateTimeOffset = new DateTimeOffset(oldest);
        var oldestUnixTime = oldestDateTimeOffset.ToUnixTimeSeconds();
        var latestDateTimeOffset = new DateTimeOffset(latest);
        var latestUnixTime = latestDateTimeOffset.ToUnixTimeSeconds();

        // クエリパラメータを作成するためにディクショナリを作成
        // ディクショナリのKeyがクエリパラメータ名、ディクショナリのValueがクエリパラメータの値
        var parameters = new Dictionary<string, string>()
        {
            { c_AccessTokenQueryParameterName, accessToken},
            { c_ChannelIdQueryParameterName, channelId},
            { c_MessageCountQueryParameterName, messageCount.ToString()},
            { c_OldestQueryParameterName, oldestUnixTime.ToString()},
            { c_LatestQueryParameterName, latestUnixTime.ToString()}
        };

        try
        {
            // クエリパラメータを作成し、文字列で読み出す
            var parametersString = await new FormUrlEncodedContent(parameters).ReadAsStringAsync();
            // 読みだしたクエリパラメータを使ってリクエストURLを作成する。
            var requestBaseUrl = "https://slack.com/api/conversations.history";
            var requestUrl = $"{requestBaseUrl}?{parametersString}";
            var response = await m_HttpClient.GetAsync(requestUrl).ConfigureAwait(false);
            // レスポンスのコンテンツをstringで読み出す
            var responseBodyString = await response.Content.ReadAsStringAsync();
            // 読みだしたJsonを、オブジェクトにデシリアライズする
            var responceObject = JsonConvert.DeserializeObject<GetSlackMessagesResponce>(responseBodyString);

            // 戻り値用のメッセージ一覧を作成
            foreach (var messageResponce in responceObject.messages)
            {
                // 本文を設定
                var message = new Message()
                {
                    Text = messageResponce.text
                };

                // 添付ファイルを設定
                foreach (var file in messageResponce.files)
                {
                    var addFile = new File()
                    {
                        FileURL = file.url_private,
                        Id = file.id,
                    };
                    message.Files.Add(addFile);
                }

                messages.Add(message);
            }

            return messages;
        }
        catch
        {
            return messages;
        }
    }

    ・・・

    #endregion
}

メソッドに新たに追加したロジックである、引数oldestとlatestをUNIX時間に変換する箇所を細かく説明します。
引数oldestとlatestはDateTime型なので、その値を使ってDateTimeOffset構造体の値を作ります。コンストラクタにDataTime型の値を渡すだけで作成できます。その後、ToUnixTimeSecondsメソッドでUNIX時間に変換します。
その後は、元々API引数として渡していたchannelIdなどと同様にディクショナリに情報を詰めます。ディクショナリのKey値がAPI引数名(oldestやlatest)、Value値が実際の値です。ディクショナリをどのようにAPI引数とするかの細かい説明は以前の記事を参照ください。

これらのロジック追加によって、oldest,latestを指定してAPIを呼び出すことが可能になりました。

まとめ

本記事では、C#からSlackAPIを利用して指定期間内に投稿されたメッセージを取得する方法をまとめました。
最も伝えたかったのは、以下2点です。

  • SlackAPIにおいて時間はUNIX時間で表現される
  • C#でUNIX時間を作るにはDateTimeOffset構造体を使うのが簡単
2
1
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
2
1