0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

discordの読み上げbot作成 -part2 (自動退室)

Last updated at Posted at 2025-03-17

🔹 関連記事

本記事はdiscordの読み上げbot作成 (Mac Intel上で作成)の続きです。

🔹 実装方法

  1. ボットがVCに参加したら、定期的にVCの状態をチェック
  2. VCに他のメンバーがいなくなったら自動で退出

✅ 実装

discord.ext.tasks を使って、定期的にVCのメンバー数を確認し、誰もいなければ切断します。

コード全体

import discord
import requests
from discord import app_commands
from discord.ext import commands, tasks
from pydub import AudioSegment

TOKEN = "YOUR_BOT_TOKEN"  # 🔴 自分のBotトークンを入れてください
VOICEVOX_URL = "http://localhost:50021"

intents = discord.Intents.default()
intents.message_content = True
intents.voice_states = True  # VCの状態を取得するために必要
bot = commands.Bot(command_prefix="/", intents=intents)

# ボットが接続しているVCのテキストチャンネルを記録
vc_text_channels = {}

@bot.event
async def on_ready():
    print(f"{bot.user} が起動しました!")
    try:
        synced = await bot.tree.sync()
        print(f"✅ スラッシュコマンド {len(synced)} 個を同期しました!")
    except Exception as e:
        print(f"❌ スラッシュコマンドの同期に失敗: {e}")

@bot.tree.command(name="join", description="ボイスチャットに参加します")
async def join(interaction: discord.Interaction):
    """ボットをVCに参加させる"""
    if interaction.user.voice:
        channel = interaction.user.voice.channel
        vc = await channel.connect()
        vc_text_channels[interaction.guild.id] = interaction.channel.id  # ボットが接続したVCのテキストチャンネルを記録
        await interaction.response.send_message("✅ ボイスチャンネルに参加しました!")

        # 🔴 チェックループが動作していない場合は開始
        if not check_empty_vc.is_running():
            check_empty_vc.start(interaction.guild)
    else:
        await interaction.response.send_message("❌ 先にボイスチャンネルに参加してください!", ephemeral=True)

@bot.tree.command(name="disconnect", description="ボイスチャットから退出")
async def disconnect(interaction: discord.Interaction):
    """ボットをVCから切断"""
    if interaction.guild.voice_client:
        await interaction.guild.voice_client.disconnect()
        vc_text_channels.pop(interaction.guild.id, None)  # 記録していたテキストチャンネルIDを削除
        check_empty_vc.cancel()  # 自動切断のチェックを停止
        await interaction.response.send_message("✅ ボイスチャンネルから切断しました!")
    else:
        await interaction.response.send_message("❌ ボットはVCにいません!", ephemeral=True)

@tasks.loop(seconds=2)
async def check_empty_vc(guild: discord.Guild):
    """VCのメンバーが0人になったら自動で切断"""
    if guild.voice_client:
        vc = guild.voice_client.channel
        members = [member for member in vc.members if not member.bot]  # 人間のみをカウント
        if len(members) == 0:
            print(f"⚠️ {vc.name} に誰もいないため、自動切断します")
            await guild.voice_client.disconnect()
            check_empty_vc.cancel()  # ループを停止
@bot.event
async def on_message(message):
    """ボットが接続しているVCのテキストチャンネルのメッセージのみを読み上げ"""

    if message.author == bot.user or message.author.bot:
        return  # ボット自身や他のBotのメッセージは無視

    # ボットがVCに接続していなければ無視
    if not message.guild or not message.guild.voice_client:
        return

    # 読み上げるメッセージ内容
    text = message.content

    # ボットが接続しているVCのテキストチャンネルか確認
    if message.guild.id not in vc_text_channels or message.channel.id != vc_text_channels[message.guild.id]:
        print(f"対象外のメッセージを無視: {text}")
        return  # VCのテキストチャンネル以外は無視


    # VOICEVOXで音声合成
    query_payload = {"text": text, "speaker": 1}
    query_response = requests.post(f"{VOICEVOX_URL}/audio_query", params=query_payload)

    if query_response.status_code != 200:
        return  # エラーなら無視

    query_data = query_response.json()
    synthesis_response = requests.post(f"{VOICEVOX_URL}/synthesis", json=query_data, params={"speaker": 1})

    if synthesis_response.status_code != 200:
        return  # エラーなら無視

    # 音声を保存(WAV形式のまま)
    wav_path = "voice.wav"
    with open(wav_path, "wb") as f:
        f.write(synthesis_response.content)

    # VCで再生(WAVをそのまま)
    source = discord.FFmpegPCMAudio(wav_path)
    message.guild.voice_client.play(source)

    await bot.process_commands(message)  # 他のコマンドも処理

bot.run(TOKEN)




🔹 実装のポイント

  • tasksモジュールをインポート
    from discord.ext import commands, tasksの箇所
  • VCに接続 (/join) すると、自動切断の監視を開始
    check_empty_vc.start(interaction.guild)の箇所
  • @tasks.loop(seconds=2) を使って2秒ごとにVCの人数をチェック
  • ボット以外の人間がVCにいない場合、自動で切断
  • VCから退出 (/disconnect) すると、監視を停止
    check_empty_vc.cancel()の箇所

✨ 使い方

  1. /join でボットをVCに招待
  2. VCに誰もいなくなると、2秒後にボットが自動で退出
  3. 手動で退出したい場合は /disconnect
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?