特定のフォルダにあるファイルの一覧を作成する
Top→Discord Botの作り方 - 1/(1+e^(-ax))
prev→Discord BotでCogを使ってみる - 1/(1+e^(-ax))
next→リストを埋め込み形式で送信する - 1/(1+e^(-ax))
前回の冒頭で少し触れましたが、コマンドを入力するたびに音楽ファイルの一覧を作るのは処理が遅くなってしまうので、起動時にファイルの一覧を作成することにします。
今回はglobという標準ライブラリを使って、手元の音楽ファイルの一覧を作る関数を実装します。
ファイルの先頭にfrom glob import globという一行を追加しておいてください。
長くなるので作成する関数のみを置いておきます。
前回作成した__BGMの中に置くことを想定して書いています。
def search_audiofiles(self): cur_path = os.getcwd() #カレントディレクトリ MUSIC_PATH = os.path.dirname(__file__) os.chdir(MUSIC_PATH) #オーディオファイルがある場所の頂点に移動 self.music_pathes = [p for p in glob('bgm/**', recursive=True) if os.path.isfile(p)] #オーディオファイルの検索(相対パス) self.music_pathes = [MUSIC_PATH + os.sep + p for p in self.music_pathes] #絶対パスに変換 os.chdir(cur_path) #カレントディレクトリを戻す return
これを__BGMの中に置いて、__init__の最後でself.search_files()で呼び出すことで、音楽ファイルの一覧を取得できます。
ただ、このままだと絶対パスしか使えないのでファイル名の一覧も作成します。
ファイル名一覧は次のようにして作成できます。
self.music_titles = [os.path.splitext(os.path.basename(path))[0] for path in self.music_pathes]
ファイル名びのついでに、拡張子も削除しています。
また、これは絶対パスの一覧と対応しているので、ここで作成したリストにある曲名とファイル名が一致したらその曲を再生キューに入れるように書き換えます。
__BGMの全体図は以下の通りです。
class __BGM(commands.Cog, name= 'BGM'): #BGMという名前でCogを定義する def search_audiofiles(self): cur_path = os.getcwd() #カレントディレクトリ MUSIC_PATH = os.path.dirname(__file__) os.chdir(MUSIC_PATH) #オーディオファイルがある場所の頂点に移動 self.music_pathes = [p for p in glob('bgm/**', recursive=True) if os.path.isfile(p)] #オーディオファイルの検索(相対パス) self.music_titles = [os.path.splitext(os.path.basename(path))[0] for path in self.music_pathes] #オーディオファイルの名前から拡張子とパスを除去したリストを作成 print(self.music_titles) self.music_pathes = [MUSIC_PATH + os.sep + p for p in self.music_pathes] #絶対パスに変換 os.chdir(cur_path) #カレントディレクトリを戻す return def __init__(self, bot): super().__init__() self.bot = bot self.audio_status = None self.path = os.path.dirname(__file__) #このファイルが置いてあるディレクトリまでのファイルパス self.search_audiofiles() #予め決めておいた音楽ファイルを再生する @commands.command() async def bgm(self, ctx, filename): """play music""" if (ctx.author.voice is None): #送信者がボイスチャンネルにいなければエラーを返す await ctx.send(f'{ctx.author.mention} ボイスチャンネルが見つかりません') return if ((self.audio_status is None) or (self.audio_status.vc is None)): #botがボイスチャンネルに入っていなければ voice_channel = ctx.author.voice.channel.id #送信者の入っているボイスチャンネルのID vc = await bot.get_channel(voice_channel).connect() #ボイスチャンネルに入る self.audio_status = AudioStatus(vc) if (len(filename) == 0): #引数無しなら全曲を追加 for f in self.music_pathes: await self.audio_status.add_audio(f) elif filename in self.music_titles: #指定された曲がある場合 idx = self.music_titles.index(filename) #リストの何番目にあるかを探す await self.audio_status.add_audio(self.music_pathes[idx]) #対応する絶対パスを再生キューに追加 else: #それ以外 await ctx.send('Audio File Not Found') return #botをボイスチャンネルから切断する @commands.command() async def remove(self, ctx): await self.audio_status.leave() return
これでファイル名を指定して再生できるようになりました。
bgmフォルダの中に適当にフォルダを作成して、その中に音楽ファイルを置いて実行してみてください。
「!bgm filename」(filenameは拡張子を除くファイル名)
次回はファイル一覧の表示をするための準備を行います。
お疲れ様でした。
next→リストを埋め込み形式で送信する - 1/(1+e^(-ax))
オマケ(拡張子だけでなくCDのトラック番号も除去する)
ファイルの先頭に「import re」、self.music_titlesの定義の後に次の4行を追加してください。
length = len(self.music_titles) for i in range(length): #トラック番号も除去 if (re.fullmatch(r'[0-9][0-9] .*', self.music_titles[i])): self.music_titles[i] = (self.music_titles[i])[3:]
これでCDのトラック番号も除去できます。