小売業で働く社内SEのブログ

技術メモを適当にかいつまんで記載します

【C#】Slackにアップしたファイルを自動削除するAWSのLambdaファンクション

元々会社で私管轄のところはSlackでコミニュケーションを取っていたのですが
ついに他とも合同で使うことになりました。
で、今まではSlackにアップしていたファイルは適当なタイミングで手動削除していたのですが流石に人数が増えてきたので自動削除されないと厳しくなり先日GAされたC#AWS Lambdaでさっそく作ってみました。

VisualStudioにAWS Lambdaの環境を構築する手順は下記ブログあたりを参照してください。
VS2015推奨です。
VS2013以下だとSDK入れてもプロジェクトテンプレートが出てこないのでS3かZIPで直接Lambdaにアップする必要があります

qiita.com

SlackのAPIリファレンスはここにあります。
サイト上でテストできるので非常に分かり易いです。
api.slack.com

で、メインのコードは以下な感じです。
AWSのシリアライザーもありそうでしたが、普通にJson.NET使いました。
stringを返していますが、テンプレートから作った初期クラスがそうなっていただけでデバッグ時以外特に意味はないです。

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Newtonsoft.Json;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializerAttribute(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace SlackDeleteFileFunction
{
    public class Function
    {
        /// <summary>
        /// Slackにアップされている1週間以上前のファイルを削除します
        /// </summary>
        /// <returns></returns>
        public string FunctionHandler()
        {
            try
            {
                return SlackFileDeleteAsync().Result;
            }
            catch (Exception e)
            {
                return e.ToString();
            }
        }

        /// <summary>
        /// ファイル削除のメイン処理
        /// </summary>
        /// <returns></returns>
        public async Task<string> SlackFileDeleteAsync()
        {
            var ret = string.Empty;

            // SlackのAPIトークン
            const string token = @"ここにトークンを記載";

            using (var httpClient = new HttpClient())
            {
                using (var response = await httpClient.GetAsync(string.Format(@"http://slack.com/api/files.list?token={0}&pretty=1", token)))
                {
                    var jsonData = JsonConvert.DeserializeObject<SlackData>(response.Content.ReadAsStringAsync().Result);
                    ret = string.Format(@"アップされているファイル数:{0}件", jsonData.Files.Count);

                    var count = 0;
                    foreach (var file in jsonData.Files)
                    {
                        if (FromUnixTime(file.Created) < DateTime.Now.AddDays(-7))
                        {
                            await httpClient.GetAsync(
                                string.Format(@"http://slack.com/api/files.delete?token={0}&file={1}&pretty=1", 
                                token,
                                file.Id));
                            count += 1;
                        }
                    }
                    ret += Environment.NewLine;
                    ret += string.Format(@"削除したファイル数:{0}件", count);
                }
            }

            return ret;
        }

        /// <summary>
        /// UnixEpochをDatetimeで表した定数
        /// </summary>
        public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        /// <summary>
        /// Unix時間からDatetimeに変換するメソッド
        /// </summary>
        /// <param name="unixTime"></param>
        /// <returns></returns>
        public static DateTime FromUnixTime(long unixTime)
        {
            return UnixEpoch.AddSeconds(unixTime);
        }

    }
}

Jsonをデシリアライズするので入れ子のクラスも以下のように準備

using System.Collections.Generic;

namespace SlackDeleteFileFunction
{
    /// <summary>
    /// Slackのデータクラス
    /// </summary>
    public class SlackData
    {
        /// <summary>
        /// ファイルリスト
        /// </summary>
        public List<FileInfo> Files { get; set; }

        /// <summary>
        /// ファイル情報
        /// </summary>
        public class FileInfo
        {
            /// <summary>
            /// ファイルID
            /// </summary>
            public string Id { get; set; }

            /// <summary>
            /// ファイルがアップされた日時
            /// </summary>
            public long Created { get; set; }
        }
    }
}

AWSにデプロイした後はTriggerを決めます。
上記ソースは1週間以上前にアップされているファイルを定期的に削除してもらうのが望ましいため
CloudWatch Eventsを1日おきにスケジューリングします。

f:id:Einherjar1632:20161223193055p:plain

AWS LambdaがC#に対応したことにより、エンプラ界でもサーバレスアーキテクチャが取っ付きやすくなりました。
VB?知らない子ですね・・・