本記事ではSlackに入力した内容をPython+Slackbotにログとして記録させる方法を紹介します。
Slackは無料プランだと10,000コメントしか保持できません。
また、有料プランの場合でも欲しい情報を探すのも意外に手間がかかります。
必要な情報だけ都度他のドキュメントに転記する面倒ですが、Slackbotを活用すればSlackに入力した内容をログとして出力可能です。
入力した内容が自動的に記録できれば手間を大幅に削減できるので、是非活用してみてください。
PythonでのSlackbot実装の基本については「SlackbotをPythonで作成しよう」をお読みください。
目次
Python+Slackbotでファイルに書き込む方法使用
Python+Slackでファイルに書き込む方法はいくつかありますが、今回はcodecsライブラリを使用して書き込みを行います。
サンプルコードは以下の通りです。
◆filereadwrite.pyの記述内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import codecs class FileReadWrite: # ファイルを読み込むメソッド def file_read(self, path): try: # ファイルを開く target_file = codecs.open(path, "r", "utf_8") # ファイルを読み込む text = target_file.read() target_file.close() except: # エラーが出た時の例外処理 text = "ng" return text # ファイルを書き込むメソッド def file_write(self, path, text): try: target_file = codecs.open(path, "a", "utf_8") target_file.write(text) result = "ok" target_file.close() except: # エラーが出た時の例外処理 result = "ng" return result |
codecsライブラリの基本的な使い方については「「codecs」の使い方〜Pythonのファイル読み書きの基本と実装例〜」をお読みください。
Slackに投稿した内容をBotに記録する方法
slackbotライブラリのデコレーター「@listen_to」を使用します。
読み取り内容を正規表現「^(.*)$」とすることで入力した全てのメッセージを受け取ることが可能です。
◆Botにおうむ返しさせる
1 2 3 | @listen_to('^(.*)$') def comment_log(message, text): message.send(text) |
受け取ったコメントを書き込む
受け取ったコメントを書き込む処理は以下の通りです。
◆記述例
1 2 3 4 5 6 7 8 9 | @listen_to('^(.*)$') def comment_log(message, text): # クラスのインスタンスを生成 f = FileReadWrite() # ファイルにデータを書き込む(末尾に改行を入れておく) action = f.file_write("test.log", text + "n") # 結果をリアクションする message.react(action) |
◆ファイルの内容
◆注意事項
・Slackbotに記録させるため、Slackbotが起動している時のみ記録されます。
・Slackbotが応答した内容は記録されません。
・コメントの編集内容は記録できません。
ファイルに書き込む時に改行を入れておかないと次に文字を入力した時に続けて文字が出力されてしまいます。
改行がない場合
改行がある場合
テスト
◆改行は文頭と文末のどちらが良い?
改行は文頭に入れる方法と文末に入れる方法があります。
先頭に改行を入れた場合最初にファイルを作成した時に1行目が空きます。
(1行目が空いていてもその後の動作に特に影響はありません)
末尾に入れる場合、ファイルの文末に改行がないと改行されずに前の文章に続けて出力されます。
どちらに入れる場合でもルールを明確にしておけば特に問題はありません。
作成するプログラムに合わせて都合のいい方に入れましょう。
Slackbotで時刻・ユーザー・チャンネルの情報も出力する
テキストだけ出力するのも味気ないので他の情報も出力するように改造について、以下の内容を追加で出力する例を説明します。
・コメント投稿の時刻
・ユーザー名
・チャンネル
時刻を出力する
時刻は「datetime」ライブラリを使用することで表示可能です。
strftime()メソッドでフォーマットを調整できます。
# 現在時刻の取得
now = datetime.datetime.now()
# 時刻を文字列に変換する
str_now = now.strftime("%Y/%m/%d %H:%M:%S")
ユーザー名を取得する
ユーザー名は「message」に格納されている情報を使用します。
ユーザー名はいくつか種類がありますが、今回はプロフィール上に表示される名前である「'real_name'」とSlack上に表示される「'display_name'」を取得する例です。
real_name = message.user['real_name'] # 表示名を取得する
display_name = message.user['profile']['display_name']
チャンネルを取得する
チャンネルは「message」に格納されている情報を使用します。
channel = message.channel._body['name']
以上をまとめたデータはコードは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | from slackbot.bot import listen_to import datetime from filereadwrite import FileReadWrite @listen_to('^(.*)$') def comment_log(message, text): target_channels = ['timeline', 'article_copy'] target_users = ['miyabikno1'] # チャンネル名を取得 channel = message.channel._body['name'] # 名前と表示名を取得する real_name = message.user['real_name'] display_name = message.user['profile']['display_name'] # 書き込みクラスのインスタンスを生成 f = FileReadWrite() # 現在時刻の取得 now = datetime.datetime.now() # 時刻を文字列に変換する str_now = now.strftime("%Y/%m/%d %H:%M:%S") # 出力情報(時刻,名前/表示名,チャンネル名,入力した文字列) output = "%s,%s/%s,%s,%sn" % (str_now, real_name, display_name, channel, text) # ファイルにデータを書き込む result = f.file_write("test.log", output) # 書き込みに失敗した場合は応答する。それ以外は無応答 if result == 'ng': message.reply("書き込みに失敗しました") |
CSVファイルやEXCELで扱いやすいようにカンマ区切りにしています。
Slackログの取得範囲を限定する
上記の内容だとSlackbotのいるチャンネルでコメントした内容が全て記録されます。
全ての会話を記録してしまうとノイズも多くなってしまうため、管理がしにくいです。
取得するチャンネルやユーザーを制限することで、記録する内容を限定していきましょう。
ログを取るチャンネルを限定する
ログを取得するチャンネルを限定する方法について説明します。
「target_channels」というリストを用意しておき、メッセージを投稿したチャンネル名がリストに含まれていた場合は終了します。
チャンネルの情報は「message.channel」オブジェクトに設定されている為この値を使用します。
チャンネルを限定する記述は以下の通りです。
1 2 3 4 5 6 7 | target_channels = ['channel1', 'channel2'] # チャンネル名を取得 channel = message.channel._body['name'] # 対象チャンネルでなければ終了する if channel not in target_channels: return |
ログを取るユーザーを限定する
ログを取得するユーザーを限定する方法について説明します。
チャンネルの時と同様に「target_users」というリストを用意しておき、投稿者と一致するかどうかをチェックします。
ユーザー情報は「message.user」オブジェクトに格納されています。
◆名前と表示名
プロフィールにある名前(real_name)の他に表示名(display_name)でもチェックできるようにします。
表示名は任意の為、名前か表示名のどちらかにヒットすればOKとします。
1 2 3 4 5 6 7 8 9 10 11 | target_users = ['user1', 'user2'] # 名前を取得する real_name = message.user['real_name'] # 表示名を取得する display_name = message.user['profile']['display_name'] # 対象ユーザーでなければ何もしない。表示名とプロフィールの名前を両方チェック if real_name not in target_users and display_name not in target_users: return |
以上をまとめたデータはコードは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | from slackbot.bot import listen_to import datetime from filereadwrite import FileReadWrite @listen_to('^(.*)$') def comment_log(message, text): target_channels = ['timeline', 'article_copy'] target_users = ['miyabikno1'] # チャンネル名を取得 channel = message.channel._body['name'] # 対象チャンネルでなければ何もしない if channel not in target_channels: return # 名前と表示名を取得する real_name = message.user['real_name'] display_name = message.user['profile']['display_name'] # 対象ユーザーでなければ何もしない if real_name not in target_users and display_name not in target_users: return # 書き込みクラスのインスタンスを生成 f = FileReadWrite() # 現在時刻の取得 now = datetime.datetime.now() # 時刻を文字列に変換する str_now = now.strftime("%Y/%m/%d %H:%M:%S") # 出力情報(時刻,名前/表示名,チャンネル名,入力した文字列) output = "%s,%s/%s,%s,%sn" % (str_now, real_name, display_name, channel, text) # ファイルにデータを書き込む result = f.file_write("test.log", output) # 書き込みに失敗した場合は応答する。それ以外は無応答 if result == 'ng': message.reply("書き込みに失敗しました") |
以上、ファイルを記録する方法でした。
Slack+PythonまとめTOP>>Slackbotの作り方マニュアル〜Python編〜