Discord Botでフォルダの階層構造を送信する
Top→Discord Botの作り方 - 1/(1+e^(-ax))
prev→リストを埋め込み形式で送信する - 1/(1+e^(-ax))
next→Discord Botで音楽再生用Botを作る(完結編) - 1/(1+e^(-ax))
ファイル構造をリストで取得した後に、それを前回作ったsend_list関数で送信するようにします。
ファイル構造を取得するmake_filetree関数は次のようになります。
import pathlib def make_filetree(path, layer=0, is_last=False, nest = -1): if (nest == 0): return '' if (nest == 1): is_last = True d = [] #pathが相対パスなら絶対パスに直す if not pathlib.Path(path).is_absolute(): path = str(pathlib.Path(path).resolve()) # カレントディレクトリの表示 current = path.split(os.sep)[::-1][0] d.append(pathlib.Path(current).parts[-1]) # 下の階層のパスを取得 paths = [p for p in glob(path+'/*') if os.path.isdir(p) or os.path.isfile(p)] def is_last_path(i): return i == len(paths)-1 # 再帰的に表示 for i, p in enumerate(paths): if os.path.isdir(p): #フォルダなら自身を再帰呼び出し d.append(make_filetree(p, layer=layer+1, is_last=is_last_path(i), nest = nest-1)) if (nest == 1): break return d #フォルダの一覧をリストで返す
処理の流れとしては指定したパスにあるフォルダ全てに対して、もう一度make_filetree()関数を適用することで最下層までのフォルダを探索しています。
また、後々使うことになる、リストの深さを返すdepth()関数も作成しておきます。
def depth(k): if not k: return 0 else: if isinstance(k, list): return 1 + max(depth(i) for i in k) else: return 0
次に、フォルダの指定を受け付けるために、音楽ファイルの一覧を作成したのと同様にフォルダ一覧も作成しておきます。
search_audiofiles()関数を次のように修正してください。
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] #オーディオファイルの名前から拡張子とパスを除去したリストを作成 self.music_pathes = [MUSIC_PATH + os.sep + p for p in self.music_pathes] #絶対パスに変換 self.music_dirs = glob(os.path.join('bgm', '**' + os.sep), recursive=True) #ディレクトリの一覧を作成(相対パス) self.mdir_name = [pathlib.Path(f).parts[-1] for f in self.music_dirs] os.chdir(cur_path) #カレントディレクトリを戻す return
これで準備が整ったので、いよいよ送信してみたいと思います。
class __BGMの中に以下のコマンドを作成します。
@commands.command() async def bgmlist(self, ctx, *dir_name): """一覧""" cur_path = os.getcwd() MUSIC_PATH = os.path.dirname(__file__) os.chdir(MUSIC_PATH) #カレントディレクトリの移動 dirname = '' for s in dir_name: #引数を1つの文字列に纏める dirname += s + ' ' dirname = dirname[:-1] if (len(dirname) == 0): #引数無しなら全てのディレクトリを表示 tree = make_filetree(MUSIC_PATH+os.sep+'bgm') await send_list(ctx.send, '', tree, delimiter = ['\n'+'....'*i+'├' for i in range(10)]) else: for f in self.music_dirs: if (dirname == pathlib.Path(f).parts[-1]): #ディレクトリ名と引数が一致した場合,表示 current = f.split(os.sep)[1:][0] tree = make_filetree(MUSIC_PATH+os.sep+f[:-1*len(os.sep)]) if (len(tree) != 1): #該当ディレクトリの下にディレクトリがあった場合は木構造を表示 result = await send_list(ctx.send, '', tree, delimiter = ['\n'+'....'*i+'├' for i in range(10)]) if (result is None): nest = depth(tree) else: #ディレクトリを持たなければオーディオファイルの一覧を表示 os.chdir(MUSIC_PATH + os.sep + f) music_titles = [os.path.splitext(os.path.basename(p))[0] for p in glob('*', recursive=True) if os.path.isfile(p)] await send_list(ctx.send, '', music_titles) break os.chdir(cur_path) #カレントディレクトリを戻す return
これで「!bgmlist」と打つとフォルダの一覧が、「!bgmlist (フォルダ名)」と撃つとそのフォルダの中身が表示されるはずです。
次回は細かい修正を行って完成としたいとおもいます。
お疲れ様でした。