1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
import discord
from discord.ext import commands
from yt_dlp import YoutubeDL
import os
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
bot = commands.Bot(command_prefix='!',intents=intents)
currentfile = None
def delete_file(path):
"""再生が終了した後にファイルを削除する関数"""
try:
os.remove(path)
print(f"Deleted file: {path}")
except Exception as e:
print(f"Error deleting file {path}: {e}")
@bot.event
async def on_ready():
print(f'ログインしました。Bot名: {bot.user.name}')
@bot.command()
async def search(ctx, *, search_query):
"""検索して一番上の結果のURLを渡す"""
ydl_opts = {
'format': 'bestaudio/best',
'quiet': True,
'extract_flat': 'in_playlist'
}
with YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(f"ytsearch:{search_query}", download=False)['entries'][0]
if info:
url = info['url']
title = info.get('title', 'Unknown title')
await ctx.send(f"検索結果: {title}\n{url}")
await play(ctx, url)
else:
await ctx.send("検索結果が見つかりませんでした。")
@bot.command()
async def play(ctx, url):
"""URLから音声をダウンロードして再生する"""
global currentfile
if not ctx.message.author.voice:
await ctx.send('先にボイスチャンネルに参加してください。')
return
channel = ctx.message.author.voice.channel
if voice_client := ctx.guild.voice_client:
await voice_client.move_to(channel)
else:
voice_client = await channel.connect()
ydl_opts = {
'format': 'bestaudio',
'outtmpl': 'tmp/%(id)s.%(ext)s', # ダウンロードするファイルのパスとフォーマット
'postprocessors': [{
'key': 'FFmpegExtractAudio', # 音声を抽出
'preferredcodec': 'opus',
'preferredquality': '96', # 96kbpsのopusに変換
}],
}
with YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
filename = ydl.prepare_filename(info)
audio_path = os.path.join('tmp', f"{info['id']}.opus") # ダウンロードしたファイルのパス
currentfile = audio_path
def after_play(error):
delete_file(audio_path)
currentfile = None
voice_client.play(discord.FFmpegPCMAudio(audio_path), after=lambda e: after_play(e))
await ctx.send(f'再生を開始します: {info["title"]}')
@bot.command()
async def stop(ctx):
global currentfile
"""音声の再生を停止し、ボイスチャンネルから切断します。"""
voice_client = ctx.guild.voice_client
if voice_client and voice_client.is_playing():
voice_client.stop()
await ctx.send('再生を停止しました。')
delete_file(currentfile)
currentfile = None
else:
await ctx.send('現在、何も再生されていません。')
@bot.command()
async def pause(ctx):
"""一時停止/再開する"""
voice_client = ctx.guild.voice_client
if voice_client and voice_client.is_playing():
voice_client.pause()
await ctx.send('一時停止しました')
elif voice_client and voice_client.is_paused():
voice_client.resume()
await ctx.send('再開しました')
else:
await ctx.send('再生されていません')
@bot.event
async def on_voice_state_update(member, before, after):
"""ボイスチャンネルにBOT以外がいなくなったら抜ける"""
# メンバーがボイスチャンネルから離れたか、別のチャンネルに移動した場合に実行
if before.channel is not None and (after.channel is None or after.channel != before.channel):
# before.channelには、メンバーが離れたボイスチャンネルの情報が含まれています
# チャンネル内のメンバー数を確認
if len(before.channel.members) == 1:
# ボット自身がそのチャンネルに接続しているか確認
voice_client = discord.utils.get(bot.voice_clients, channel=before.channel)
if voice_client is not None:
# チャンネルから抜ける
await voice_client.disconnect()
print(f"{before.channel.name}から抜けました。")
@bot.command()
async def leave(ctx):
await ctx.voice_client.disconnect()
bot.run('TOKEN')
|