2024/09時点で最新の実装まとめ
Pipfile
- 現時点においてはPycordの利用を推奨
[packages]
python-dotenv = "*"
py-cord = "*"
tzdata = "*"
.env
.env
DISCORD_BOT_TOKEN=xxxxxxxx
TARGET_GUILD_ID=1234567890
LOG_DIR_PATH=.log
実装
- 投稿用に1ファイルにまとめたので適宜分割を
import os
from datetime import datetime
from zoneinfo import ZoneInfo
from dotenv import load_dotenv
from discord import Bot
from discord.commands import Option
# Initialize - start
load_dotenv()
DISCORD_BOT_TOKEN: str = os.getenv('DISCORD_BOT_TOKEN', '')
LOG_DIR_PATH: str = os.getenv('LOG_DIR_PATH', os.path.dirname(__file__))
TARGET_GUILD_ID: int = int(os.getenv('TARGET_GUILD_ID', '0'))
os.makedirs(LOG_DIR_PATH, exist_ok=True)
bot = Bot()
# 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(guild_name: str) -> str:
return os.path.join(LOG_DIR_PATH, f"{guild_name}_{get_date_today_jst()}.log")
# Utility functions - end
# Slash command: sample1
@bot.slash_command(guild_ids=[ TARGET_GUILD_ID ], description='sample command 1.')
async def sample(
context,
param1: Option(str, 'parameter 1', choices=[ 'a', 'b', 'c' ], required=True),
param2: Option(str, 'parameter 2', choices=[ 'x', 'y', 'z' ], required=False),
):
await context.respond(f"{context.author.display_name}: {param1}, {param2}")
# Slash command: sample2
@bot.slash_command(guild_ids=[ TARGET_GUILD_ID ], description='sample command 2.')
async def foo(
context,
):
await context.respond("bar")
# Event listener: logging
@bot.event
async def on_message(message):
if message.guild.id != TARGET_GUILD_ID:
# ignore non-logging targets
return
if message.author == bot.user:
# ignore bot messages
return
with open(create_log_path(message.guild.name), 'a', encoding='UTF-8') as log_file:
log_file.write(f"{message.author.display_name}: {message.content}\n")
# Entry point
bot.run(DISCORD_BOT_TOKEN)