처벌 로그 디스코드 봇 만들기

2026. 5. 4. 16:55·봇 개발 팁/Discord.py

경고, 타임아웃, 킥, 밴 같은 처벌은 남길수록 민감해집니다.

그만큼 누가 왜 조치했는지 기록이 없으면 운영진 내부에서도 기준이 흐려지기 쉽습니다.

처벌 로그 봇은 제재 자체보다 제재 이력을 일정한 형식으로 남기는 데 의미가 있습니다.

이번 글에서는 슬래시 명령어로 경고를 기록하고, 타임아웃 로그를 남기는 기본 구조를 만듭니다.

1. 왜 별도 로그가 필요한가

메시지 삭제 로그나 입장 로그와 달리 처벌 기록은 나중에 다시 볼 일이 많습니다.

재제 기준이 일관됐는지, 특정 유저에게 어떤 이력이 쌓였는지 확인할 때 필요합니다.

신고 흐름과 같이 붙여 볼 계획이라면 문의·운영 동선이 섞이지 않게 먼저 분리해 둬야 합니다.

2. 처벌 로그 채널 값 정리

DISCORD_TOKEN=여기에_봇_토큰
GUILD_ID=테스트_서버_ID
MOD_LOG_CHANNEL_ID=처벌로그채널_ID
MOD_ROLE_ID=운영진역할_ID


처벌 로그 채널은 운영진만 보게 두는 것이 기본입니다.

3. 제재 기록을 남기는 기본 코드

import os
from datetime import timedelta

import discord
from discord import app_commands
from dotenv import load_dotenv

load_dotenv()

TOKEN = os.getenv("DISCORD_TOKEN")
GUILD_ID = int(os.getenv("GUILD_ID"))
MOD_LOG_CHANNEL_ID = int(os.getenv("MOD_LOG_CHANNEL_ID"))
MOD_ROLE_ID = int(os.getenv("MOD_ROLE_ID"))

intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)
guild = discord.Object(id=GUILD_ID)


def is_moderator(member: discord.Member, mod_role_id: int) -> bool:
    return any(role.id == mod_role_id for role in member.roles)


async def send_mod_log(guild_obj: discord.Guild, title: str, lines: list[str], color: discord.Color):
    channel = guild_obj.get_channel(MOD_LOG_CHANNEL_ID)
    if not isinstance(channel, discord.TextChannel):
        return

    embed = discord.Embed(title=title, description="\n".join(lines), color=color)
    await channel.send(embed=embed)


@client.event
async def on_ready():
    await tree.sync(guild=guild)
    print(f"로그인 성공: {client.user}")


@tree.command(name="경고", description="유저 경고 로그를 남깁니다.", guild=guild)
@app_commands.describe(user="경고할 유저", reason="경고 사유")
async def warn_user(interaction: discord.Interaction, user: discord.Member, reason: str):
    if interaction.guild is None or not isinstance(interaction.user, discord.Member):
        await interaction.response.send_message("서버 안에서만 사용할 수 있습니다.", ephemeral=True)
        return

    if not is_moderator(interaction.user, MOD_ROLE_ID):
        await interaction.response.send_message("운영진만 사용할 수 있습니다.", ephemeral=True)
        return

    await send_mod_log(
        interaction.guild,
        "경고 로그",
        [
            f"대상: {user.mention}",
            f"처리자: {interaction.user.mention}",
            f"사유: {reason}",
        ],
        discord.Color.orange(),
    )
    await interaction.response.send_message("경고 로그를 남겼습니다.", ephemeral=True)


@tree.command(name="타임아웃", description="유저를 일정 시간 타임아웃 처리합니다.", guild=guild)
@app_commands.describe(user="타임아웃할 유저", minutes="타임아웃 시간(분)", reason="사유")
async def timeout_user(interaction: discord.Interaction, user: discord.Member, minutes: int, reason: str):
    if interaction.guild is None or not isinstance(interaction.user, discord.Member):
        await interaction.response.send_message("서버 안에서만 사용할 수 있습니다.", ephemeral=True)
        return

    if not is_moderator(interaction.user, MOD_ROLE_ID):
        await interaction.response.send_message("운영진만 사용할 수 있습니다.", ephemeral=True)
        return

    try:
        await user.timeout(timedelta(minutes=minutes), reason=reason)
        await send_mod_log(
            interaction.guild,
            "타임아웃 로그",
            [
                f"대상: {user.mention}",
                f"처리자: {interaction.user.mention}",
                f"시간: {minutes}분",
                f"사유: {reason}",
            ],
            discord.Color.red(),
        )
        await interaction.response.send_message("타임아웃 처리와 로그 기록이 완료되었습니다.", ephemeral=True)
    except discord.Forbidden:
        await interaction.response.send_message("봇 권한이 부족해 타임아웃을 처리하지 못했습니다.", ephemeral=True)


if not TOKEN:
    raise ValueError("DISCORD_TOKEN 값이 없습니다.")

client.run(TOKEN)


핵심은 `처벌 실행`과 `처벌 기록`을 같은 흐름으로 묶는 점입니다.
기록만 남기는 명령어와 실제 제재 명령어를 분리해 두면 운영 기준을 잡기 쉽습니다.

4. 로그 형식부터 먼저 맞춰 보기

python main.py


테스트 서버에서 운영진 역할이 붙은 계정으로 `/경고`, `/타임아웃`을 실행해 봅니다.
로그 채널에 기록이 남고, 타임아웃 대상 유저가 실제로 채팅을 못 치면 정상입니다.

5. 제재 기록에서 자주 빠지는 값

  • 타임아웃이 안 되는 경우 봇 역할이 대상 유저 역할보다 낮거나 Moderate Members 권한이 없을 수 있습니다.
  • 경고 명령어가 아무나 실행되는 경우 역할 체크를 빠뜨렸을 가능성이 큽니다.
  • 로그 채널에 안 남는 경우 채널 ID 오류나 채널 접근 권한 부족을 먼저 봅니다.

6. 로그 형식은 최대한 고정한다

처벌 로그마다 문구가 제각각이면 나중에 검색하기 어렵습니다.

대상, 처리자, 사유, 시간 정도는 항상 같은 순서로 남겨야 합니다.

이 일관성이 운영팀 내부 기준을 만드는 데도 도움이 됩니다.

7. 신고 흐름과 같이 붙으면 더 유용하다

처벌 기록은 보통 신고 처리 뒤에 생깁니다.

그래서 신고 접수 채널, 티켓, 처벌 로그는 서로 연결되는 경우가 많습니다.

문의 구조는 티켓 디스코드 봇 만들기, 동선은 디스코드 문의 동선 설계법과 같이 보면 흐름이 잘 맞습니다.

8. 실제 운영에서는 증거 링크도 남겨야 한다

경고 사유만 짧게 적으면 나중에 판단이 어려울 수 있습니다.

가능하다면 메시지 링크, 스크린샷 위치, 신고 채널 티켓 링크도 같이 남겨야 합니다.

이번 글에서는 가장 기본적인 기록 구조만 넣었습니다.

9. 상시 운영용이라 배포가 필요하다

처벌 로그도 사건이 생길 때 바로 남아야 의미가 있습니다.

실운영에서는 결국 계속 켜져 있어야 합니다.

배포까지 같이 보려면 24시간 디스코드 봇 무료 호스팅, 디스호스트처럼 상시 실행 환경을 같이 준비해야 합니다.

10. 처벌 기록은 신고 접수와 붙을 때 힘이 난다

처벌 기록까지 잡았다면 이제 신고 채널 자체를 어떻게 운영할지 기준을 세우는 단계가 이어집니다.

로그 구조 전체를 다시 보고 싶다면 디스코드 로그 기록 봇 만들기와 입장 퇴장 로그 디스코드 봇 만들기를 같이 보면 됩니다.

'봇 개발 팁 > Discord.py' 카테고리의 다른 글

입장 퇴장 로그 디스코드 봇 만들기  (0) 2026.05.03
디스코드 로그 기록 봇 만들기  (0) 2026.05.02
디스코드 모달 입력창 기본 사용법  (0) 2026.05.01
모달 폼 접수 디스코드 봇 만들기  (0) 2026.04.30
지원서 접수 디스코드 봇 만들기  (0) 2026.04.29
'봇 개발 팁/Discord.py' 카테고리의 다른 글
  • 입장 퇴장 로그 디스코드 봇 만들기
  • 디스코드 로그 기록 봇 만들기
  • 디스코드 모달 입력창 기본 사용법
  • 모달 폼 접수 디스코드 봇 만들기
디스호스트
디스호스트
쉽고 안정적인 디스코드 봇 호스팅 서비스, 디스호스트의 기술 블로그입니다. 디스호스트는 24시간 구동되는 서버를 통해 디스코드 봇을 대신 구동시켜 드리는 서비스를 제공하고 있습니다.
  • 디스호스트
    디스호스트 기술 블로그
    디스호스트
  • 블로그 메뉴

    • 홈
    • 디스호스트 사용 가이드
    • 디스코드 봇 호스팅, 24시간 서버 구동
    • 분류 전체보기 (96) N
      • 디스코드 (9)
      • 디스호스트 가이드 (12)
      • 봇 개발 팁 (35) N
        • Discord.js (11)
        • Discord.py (23) N
      • DiscordJS 개발 튜토리얼 (15)
      • 디스코드 서버 운영 (17)
      • 디스코드 봇 오류 해결 (7)
  • 링크

    • 디스호스트
  • hELLO· Designed By정상우.v4.10.3
디스호스트
처벌 로그 디스코드 봇 만들기
상단으로

티스토리툴바