Ну подумай головой.
> 'NoneType' object has no attribute '
play'
> voice_channel.
play(
Значит, voice_channel - None.
Смотрим откуда он взялся, читаем
доки по Guild.voice_client:
"voice_client - Returns the VoiceProtocol associated with this guild,
if any.
Type:
Optional[VoiceProtocol]"
Т.е. он вполне может быть None, и это надо проверять перед использованием.
А вот более интересный вопрос, почему он None.
Ты выше обращаешься к channel = ctx.author.voice.channel - а ведь не только voice может быть None, но и channel в нём. voice проверяешь, channel нет. А чуть ниже у тебя удивительная конструкция:
try:
await channel.connect()
except:
pass
Дай угадаю, channel.connect() кидал 'NoneType' object has no attribute 'connect'?
Никогда на надо глотать исключения таким образом - всё без разбора и без реакции.
channel.connect() кидает ровно три возможных исключения, и их нужно обрабатывать по-нормальному!
asyncio.TimeoutError – серверу икнулось, мы ничего сделать не можем, только попросить пользователя повторить по-позже.
ClientException – мы уже к войс-чату подключены, нужно либо переключаться, либо просить подождать, пока закончим с первым запросом.
OpusNotLoaded – библиотеку opus не загрузил, она нужна для работы с голосом.
Ещё раз, except: pass - это очень, очень хороший способ выстрелить себе в ногу.
И самое-то смешное, что в
документации на connect() написано что оно возвращает готовый к работе voice_channel. Тогда вроде как не нужно было ctx.guild.voice_client трогать, connect() отдаст нужный объект.