カテゴリー: Discordボット開発
Discordボット開発#13ロール・チャンネルの自動化でサーバーを管理しよう! (Pythonサンプル付き)
この記事は韓国語の原文から翻訳したものです。
目次9項目
こんにちは!Mojangcamです 😎
前回の#12では、コマンドのクールダウンと権限でボットを安全に守る方法を学びました。今回の#13ではさらに一歩進んで、サーバー管理者の繰り返し作業をまるごとボットに任せてみます。今日作る自動化はちょうど3つです。
- 新しいメンバーが参加したら自動でロールを付与 (歓迎ロール)
- ボタンひとつで好きなロールを自分で取得 (ロールボタンパネル)
- ボイスチャンネルに入ったら個人部屋を自動作成 (Join to Create)
サーバーが大きくなるほど、「新しく来た人にロールを付ける」「ゲームする人にロールを配る」「会議用の部屋を作る」といった作業が延々と繰り返されます。これを人の手でやっていたら、徹夜しても終わりません。ボットに任せれば、24時間自動で処理してくれます。それでは始めましょう! 🙌
📌 準備するもの
まずは開発環境から準備しましょう。
- Python 3.9以上 (
discord.py2.7には3.9+が必要) discord.py2.x (2026年7月時点の最新安定版は 2.7.1)
ライブラリのインストールは、ターミナルで1行打つだけで終わりです。
pip install -U discord.pyそれから今回は、特権インテント(Privileged Intents) の設定が必ず必要です。新しいメンバーの参加を検知するには、Server Members Intentをオンにしなければならないからです。
- Discord Developer Portalにアクセス → 自分のボットを選択
- 左のBotタブ → Privileged Gateway Intents
- Server Members Intentをオン ✅ (メッセージコマンドを使うならMessage Content Intentもオン)
最後に、サーバーでボットのロールの権限も確認します。自動化が動くには、ボットに次の権限が必要です。
- ロールの管理(Manage Roles) — ロールを付けたり外したりする
- チャンネルの管理(Manage Channels) — ボイスチャンネルを作ったり消したりする
- メンバーを移動(Move Members) — 作った部屋へメンバーを移す
💡 いちばん大事なポイント! ボットが付与するロールは、必ずボット自身のロールより下になければいけません。サーバー設定 → ロール一覧で、ボットのロールを上のほうへドラッグしてください。これを見落とすと、後で出てくる
Forbiddenエラーになります。
📌 ステップ1 - 新しいメンバーが来たら自動でロールを付与
まずはいちばん基本となる、自動の歓迎ロールから作ります。誰かがサーバーに入った瞬間にon_member_joinイベントが実行されます。ここでロールを探して付ければ完成です。
import discord
from discord.ext import commands
intents = discord.Intents.default()
intents.members = True # メンバーの参加を検知 (特権インテント)
intents.message_content = True # プレフィックスコマンド用
bot = commands.Bot(command_prefix="!", intents=intents)
AUTO_ROLE_NAME = "若葉" # 参加時に自動で付与するロール名
@bot.event
async def on_member_join(member: discord.Member):
role = discord.utils.get(member.guild.roles, name=AUTO_ROLE_NAME)
if role is not None:
await member.add_roles(role)
print(f"👋 {member.name} さんに「{role.name}」ロールを付与しました!")ひとつずつ見ていきましょう 💡
intents.members = True: メンバーの参加・退出を検知するスイッチです。これがオフだと、on_member_joinがそもそも実行されません。on_member_join(member): 新しいメンバーが入るたびに自動で呼ばれるイベントです。memberに入ってきた人の情報が入っています。discord.utils.get(member.guild.roles, name=...): サーバーのロール一覧から、名前が一致するロールを探してくれます。なければNoneを返すので、必ず確認しましょう。await member.add_roles(role): 見つけたロールをそのメンバーに付けます。核心となる1行ですね!
あとは「若葉」というロールをサーバーに作っておけば、新しいメンバーは入ってくるなり若葉ロールを付けて登場します。🌱
📌 ステップ2 - ボタンひとつでロールを自分で取得
以前の#5 ボタン(Button)編でボタンを学びましたよね?今回はそのボタンで、メンバーが自分でロールを選べるパネルを作ります。管理者がいちいちロールを付けてあげる必要がなくなります。
ここで必ず知っておきたい概念が永続View(Persistent View) です。ボットを再起動すると普通はボタンが反応しなくなりますが、次の2つの条件を守れば、再起動後もボタンが動き続けます。
- Viewの
timeout=None - すべてのボタンに
custom_idを指定
# ボタンロールの一覧 (custom_id, ロール名, ボタンのラベル, 絵文字)
BUTTON_ROLES = [
("role_notice", "お知らせ通知", "お知らせ通知", "🔔"),
("role_game", "ゲーム仲間", "ゲーム仲間", "🎮"),
("role_study", "勉強仲間", "勉強仲間", "📚"),
]
class RoleButton(discord.ui.Button):
def __init__(self, custom_id, role_name, label, emoji):
super().__init__(
label=label, emoji=emoji,
style=discord.ButtonStyle.secondary,
custom_id=custom_id, # 永続Viewにはcustom_idが必須!
)
self.role_name = role_name
async def callback(self, interaction: discord.Interaction):
role = discord.utils.get(interaction.guild.roles, name=self.role_name)
if role is None:
await interaction.response.send_message(
f"❌ 「{self.role_name}」ロールがありません。先にサーバーで作成してください!",
ephemeral=True)
return
if role in interaction.user.roles:
await interaction.user.remove_roles(role)
msg = f"「{role.name}」ロールを外しました。👋"
else:
await interaction.user.add_roles(role)
msg = f"「{role.name}」ロールを付与しました! 🎉"
await interaction.response.send_message(msg, ephemeral=True)
class RoleView(discord.ui.View):
def __init__(self):
super().__init__(timeout=None) # 永続Viewはtimeout=None!
for custom_id, role_name, label, emoji in BUTTON_ROLES:
self.add_item(RoleButton(custom_id, role_name, label, emoji))ひとつずつ見ていきましょう 💡
custom_id: ボタンごとに付ける固有の名札です。再起動後にボットが「あ、このボタンはあのボタンだ!」と見分けられるようにしてくれます。永続Viewの必須条件です。callback(self, interaction): ボタンが押されたときに実行される関数です。interaction.userがボタンを押した人です。role in interaction.user.roles: すでにそのロールがあれば外し(remove_roles)、なければ付けます(add_roles)。ボタンひとつでトグルになるわけです。ephemeral=True: 「自分にだけ見えるメッセージ」です。ほかの人の画面を散らかさずに、こっそり知らせてくれます。
次に、このパネルをチャットに表示するコマンドと、再起動後もボタンが生き続けるようにするコードを追加します。
class MyBot(commands.Bot):
def __init__(self):
super().__init__(command_prefix="!", intents=intents)
async def setup_hook(self):
self.add_view(RoleView()) # 再起動後にボタンを復活させる
bot = MyBot()
@bot.command(name="역할판")
@commands.has_permissions(administrator=True)
async def role_panel(ctx: commands.Context):
embed = discord.Embed(
title="🎭 ロールを受け取る",
description="ボタンを押すとロールを付与します!もう一度押すとロールが外れます。",
color=0x5865F2,
)
await ctx.send(embed=embed, view=RoleView())setup_hook+add_view: ボットの起動時に永続Viewを再登録します。この2行のおかげで、ボットを再起動しても、以前に表示しておいたボタンがそのまま動きます。@commands.has_permissions(administrator=True): 管理者だけが!역할판コマンドを使えるように制限します。

📌 ステップ3 - 入ったら個人ボイスチャンネルを自動作成
最後は、最近のサーバーならどこでも使っているJoin to Createです。「➕ チャンネル作成」のようなボイスチャンネルをひとつ作っておき、誰かがそこに入ると、その人専用の部屋をその場で作って移動させる機能です。部屋が空になると自動で消えるので、サーバーもすっきり保てます。
ボイスチャンネルの移動はon_voice_state_updateイベントで検知します。
CREATOR_CHANNEL_ID = 123456789012345678 # 「➕ チャンネル作成」ボイスチャンネルのID
temp_channels = set() # 自分たちが作った一時チャンネルのIDを保管
@bot.event
async def on_voice_state_update(member, before, after):
# (作成) 「作成」チャンネルに入ったら個人チャンネルを作って移動
if after.channel is not None and after.channel.id == CREATOR_CHANNEL_ID:
new_channel = await member.guild.create_voice_channel(
name=f"🔊 {member.display_name}の部屋",
category=after.channel.category,
)
temp_channels.add(new_channel.id)
await member.move_to(new_channel)
# (削除) 自分たちが作った一時チャンネルが空になったら削除
if before.channel is not None and before.channel.id in temp_channels:
if len(before.channel.members) == 0:
await before.channel.delete()
temp_channels.discard(before.channel.id)ひとつずつ見ていきましょう 💡
on_voice_state_update(member, before, after): 誰かがボイスチャンネルを移動するたびに実行されます。beforeは抜けたチャンネル、afterは入ったチャンネルです。after.channel.id == CREATOR_CHANNEL_ID: たった今入ったのが「作成」チャンネルかどうかを確認します。そうなら、新しい部屋を作る番です!create_voice_channel(name, category): 個人ボイスチャンネルを作ります。categoryを元のチャンネルと同じにすると、同じカテゴリーの下にきれいに作られます。member.move_to(new_channel): 作ったばかりの部屋へメンバーをスッと移動させます。len(before.channel.members) == 0: 抜けた部屋に誰も残っていなければ、delete()で消します。temp_channelsで「自分たちが作った部屋」だけを消すように安全装置を付けています。
💡
CREATOR_CHANNEL_IDは、Discordで開発者モードをオンにしてから(設定 → 詳細設定 → 開発者モード)、作成用のボイスチャンネルを右クリック → 「IDをコピー」で取得できます。
📌 全体コード (コピペOK)
下のコードをコピーして、TOKEN、AUTO_ROLE_NAME、CREATOR_CHANNEL_ID、BUTTON_ROLESだけを自分のサーバーに合わせて変えれば、すぐに動きます。
# discord.py 2.x (2.7.1 基準) / Python 3.9+
import discord
from discord.ext import commands
# ── 設定 ──────────────────────────────
TOKEN = "ここにボットのトークン"
AUTO_ROLE_NAME = "若葉" # 参加時に自動で付与するロール名
CREATOR_CHANNEL_ID = 123456789012345678 # 「➕ チャンネル作成」ボイスチャンネルのID
# ボタンロールの一覧 (custom_id, ロール名, ボタンのラベル, 絵文字)
BUTTON_ROLES = [
("role_notice", "お知らせ通知", "お知らせ通知", "🔔"),
("role_game", "ゲーム仲間", "ゲーム仲間", "🎮"),
("role_study", "勉強仲間", "勉強仲間", "📚"),
]
intents = discord.Intents.default()
intents.members = True # メンバーの参加を検知 (特権インテント)
intents.message_content = True # プレフィックスコマンド用
# voice_states は default() にすでに含まれています。
# ── ボタンロールのView ────────────────────
class RoleButton(discord.ui.Button):
def __init__(self, custom_id, role_name, label, emoji):
super().__init__(
label=label, emoji=emoji,
style=discord.ButtonStyle.secondary,
custom_id=custom_id, # 永続Viewにはcustom_idが必須!
)
self.role_name = role_name
async def callback(self, interaction: discord.Interaction):
role = discord.utils.get(interaction.guild.roles, name=self.role_name)
if role is None:
await interaction.response.send_message(
f"❌ 「{self.role_name}」ロールがありません。先にサーバーで作成してください!",
ephemeral=True)
return
if role in interaction.user.roles:
await interaction.user.remove_roles(role)
msg = f"「{role.name}」ロールを外しました。👋"
else:
await interaction.user.add_roles(role)
msg = f"「{role.name}」ロールを付与しました! 🎉"
await interaction.response.send_message(msg, ephemeral=True)
class RoleView(discord.ui.View):
def __init__(self):
super().__init__(timeout=None) # 永続Viewはtimeout=None!
for custom_id, role_name, label, emoji in BUTTON_ROLES:
self.add_item(RoleButton(custom_id, role_name, label, emoji))
# ── ボット本体 ───────────────────────────
class MyBot(commands.Bot):
def __init__(self):
super().__init__(command_prefix="!", intents=intents)
async def setup_hook(self):
# 再起動後もボタンが動くように永続Viewを再登録
self.add_view(RoleView())
bot = MyBot()
temp_channels = set() # 自分たちが作った一時ボイスチャンネルのIDを保管
@bot.event
async def on_ready():
print(f"✅ {bot.user} でログインしました!")
# 1) 参加したら自動でロールを付与
@bot.event
async def on_member_join(member: discord.Member):
role = discord.utils.get(member.guild.roles, name=AUTO_ROLE_NAME)
if role is not None:
await member.add_roles(role)
print(f"👋 {member.name} → 「{role.name}」ロールの付与が完了")
# 2) ロールボタンのパネルを表示 (管理者のみ)
@bot.command(name="역할판")
@commands.has_permissions(administrator=True)
async def role_panel(ctx: commands.Context):
embed = discord.Embed(
title="🎭 ロールを受け取る",
description="ボタンを押すとロールを付与します!もう一度押すとロールが外れます。",
color=0x5865F2,
)
await ctx.send(embed=embed, view=RoleView())
# 3) 指定チャンネルに入ったら個人ボイスチャンネルを自動作成 + 空になったら削除
@bot.event
async def on_voice_state_update(member, before, after):
# (作成) 「作成」チャンネルに入ったら個人チャンネルを作って移動
if after.channel is not None and after.channel.id == CREATOR_CHANNEL_ID:
new_channel = await member.guild.create_voice_channel(
name=f"🔊 {member.display_name}の部屋",
category=after.channel.category,
)
temp_channels.add(new_channel.id)
await member.move_to(new_channel)
# (削除) 自分たちが作った一時チャンネルが空になったら削除
if before.channel is not None and before.channel.id in temp_channels:
if len(before.channel.members) == 0:
await before.channel.delete()
temp_channels.discard(before.channel.id)
bot.run(TOKEN)📌 実行結果
ボットを起動して、サーバーでひとつずつ確認してみましょう。
- 新しいアカウントで参加 → 自動で「若葉」ロールがピタッと付きます。🌱
- 管理者が
!역할판と入力 → ボタンが3つ付いた埋め込みが表示されます。ボタンを押すと「ロールを付与しました! 🎉」、もう一度押すと「ロールを外しました 👋」と、自分にだけ見えるメッセージで返事をしてくれます。 - 「➕ チャンネル作成」ボイスチャンネルに入る → すぐに「🔊 (自分の名前)の部屋」ができて、そこへ移動します。部屋から出ると、部屋はスーッと消えます。
📌 よくあるエラー
1. discord.errors.Forbidden: 403 Missing Permissions
原因: ボットに権限がないか、付与しようとしているロールがボットのロールより上にあります。
解決: サーバー設定 → ロールでボットのロールを上へ移動し、ボットにロールの管理 / チャンネルの管理 / メンバーを移動の権限を付けてください。Discordは「自分より上のロール」には絶対に手を出せないようにしています。
2. on_member_joinがまったく実行されない
原因: Server Members Intentがオフになっています。
解決: Developer Portal → Bot → Privileged Gateway IntentsでServer Members Intentをオンにし、コードにもintents.members = Trueを入れます。両方オンにしないと動きません。
3. ボットを再起動したらボタンが「インタラクションに失敗しました」
原因: 永続Viewの条件を守っていません。
解決: Viewはtimeout=None、すべてのボタンはcustom_idを持ち、setup_hookでadd_viewを使って再登録しているか確認してください。3つでワンセットです。
4. 一時ボイスチャンネルが消えない
原因: ボットにチャンネルの管理権限がないか、temp_channelsにIDが入っていません。
解決: チャンネルの管理権限を確認し、チャンネルを作るときにtemp_channels.add(...)でIDを保存しているか点検してください。
📌 まとめ
今回は、サーバー管理をまるごとボットに任せる3つの自動化を作ってみました。参加時の自動ロール、ボタンでのロール自己取得、ボイスチャンネルの自動作成まで — この3つがあるだけで、管理者の繰り返し作業がぐっと減ります。特に永続View(timeout=None + custom_id + add_view)は、これからどんなボタンやメニューを作るときにもずっと使うので、ぜひ身につけておいてください! 💪
次の#14では、JSONとSQLiteでボットのデータを保存する方法を扱います。ロール・設定・記録を、ボットを再起動しても失わないようにするわけです。お楽しみに! 🙌
📚 Discordボット開発シリーズ
- #5 - ボタン(Button)のインタラクション
- #6 - ドロップダウン(Select Menu)メニュー
- #7 - モーダル(Modal)で入力を受け取る
- #8 - 埋め込み(Embed)を飾る
- #9 - AI(Claude・ChatGPT API)との連携
- #10 - 多言語(i18n)対応
- #11 - Flask Webダッシュボード
- #12 - コマンドのクールダウン・権限管理
- #13 - ロール・チャンネルの自動化 ← 今読んでいる記事!
連載 · 全32回中13回目
Discordボット開発
- #1Discordボット開発 - スラッシュコマンド(Slash Command)完全攻略!
- #2スラッシュコマンドにオプション(Arguments)を追加しよう!
- #3スラッシュコマンドにサブコマンド(Subcommand)を追加しよう!
- #4スラッシュコマンドで埋め込み(Embed)を送信しよう!
- #5ボタン(Button)のインタラクションを実装しよう!
- #6ドロップダウン(Select Menu)メニューを実装しよう!
- #7モーダル(Modal)で入力を受け取る方法 (Pythonサンプル付き)
- #8埋め込み(Embed)を画像・フィールドで飾る (Pythonサンプル付き)
- #9AI(Claude・ChatGPT API)と連携する! (Pythonサンプル付き)
- #10多言語(i18n)に対応する! (Pythonサンプル付き)
- #11FlaskでWebダッシュボードを作る! (Pythonサンプル付き)
- #12コマンドのクールダウン(Cooldown)・権限(Permission)を管理しよう! (Pythonサンプル付き)
- #13ロール・チャンネルの自動化でサーバーを管理しよう! (Pythonサンプル付き)現在の記事
- #14データを保存しよう!JSON vs SQLite (Pythonサンプル付き)
- #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제) (韓国語)
- #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제) (韓国語)
- #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제) (韓国語)
- #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제) (韓国語)
- #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제) (韓国語)
- #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제) (韓国語)
- #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제) (韓国語)
- #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제) (韓国語)
- #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제) (韓国語)
- #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제) (韓国語)
- #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제) (韓国語)
- #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제) (韓国語)
- #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제) (韓国語)
- #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제) (韓国語)
- #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제) (韓国語)
- #30投票・アンケート(Poll)ボットを作ろう!ネイティブ投票+ボタンでリアルタイム集計まで(Pythonサンプル) 🗳️
- #32サーバーログ・監査ログ(Audit Log)チャンネルを作ろう!メッセージの削除・編集・入退室・キックまで自動記録(Pythonサンプル) 🕵️
- #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉 (韓国語)
