2024/09時点で最新の実装まとめ
Pipfile
[packages]
python-dotenv = "*"
slack-bolt = "*"
tzdata = "*"
.env
.env
SLACK_APP_TOKEN=xapp-xxxxxxxx
SLACK_BOT_TOKEN=xoxb-xxxxxxxx
TARGET_CHANNEL_ID=xxxxxxxx
LOG_DIR_PATH=.log
実装
- 投稿用に1ファイルにまとめたので適宜分割を
import os
import re
from datetime import datetime
from zoneinfo import ZoneInfo
from dotenv import load_dotenv
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
# Initialize - start
load_dotenv()
SLACK_APP_TOKEN: str = os.getenv('SLACK_APP_TOKEN', '')
SLACK_BOT_TOKEN: str = os.getenv('SLACK_BOT_TOKEN', '')
LOG_DIR_PATH: str = os.getenv('LOG_DIR_PATH', os.path.dirname(__file__))
TARGET_CHANNEL_ID: str = os.getenv('TARGET_CHANNEL_ID', '')
os.makedirs(LOG_DIR_PATH, exist_ok=True)
app = App(token=SLACK_BOT_TOKEN)
# Initialize - end
# Utility functions - start
def get_date_today_jst() -> str:
# YYMMDD
return datetime.now(ZoneInfo('Asia/Tokyo')).strftime('%Y%m%d')
def create_log_path(channel_id: str) -> str:
return os.path.join(LOG_DIR_PATH, f"{channel_id}_{get_date_today_jst()}.log")
# Utility functions - end
# Message listener: sample1
@app.message(re.compile(r'aaa|bbb'))
def echo(message, say):
say(f"<@{message['user']}> {message['text']}")
# Message listener: sample2
@app.message(re.compile(r'foo+'))
def on_foo(message, say):
say("bar")
# Event listener: logging
# MUST be placed after message listeners
@app.event('message')
def logging(event, client):
if 'subtype' in event:
# ignore system messages
return
if event['channel'] != TARGET_CHANNEL_ID:
# ignore non-logging targets
return
user_info = client.users_info(user=event['user'])
user_name = user_info['user']['name']
if user_name.endswith('bot'):
# ignore bot messages
return
with open(create_log_path(TARGET_CHANNEL_ID), 'a', encoding='UTF-8') as log_file:
log_file.write(f"{user_name}: {event['text']}\n")
# Entry point
if __name__ == '__main__':
SocketModeHandler(app, SLACK_APP_TOKEN).start()