v0.0.6\nplay_audio fixes

This commit is contained in:
bot
2024-03-07 02:18:09 +03:00
parent d75add614b
commit 53939b4bc3
22 changed files with 1126 additions and 1104 deletions

View File

@@ -1,6 +1,6 @@
__version__ = '0.0.5' __version__ = '0.0.6'
__title__ = "Pisya_bot" __title__ = "Pisya_bot"
__author__ = "beaconborn" __author__ = "baconborn"
from typing import NamedTuple, Literal from typing import NamedTuple, Literal
@@ -13,4 +13,4 @@ class VersionInfo(NamedTuple):
serial: int serial: int
version_info: VersionInfo = VersionInfo(major=5, minor=0, micro=5, releaselevel="alpha", serial=0) version_info: VersionInfo = VersionInfo(major=0, minor=0, micro=6, releaselevel="alpha", serial=0)

29
bot.py
View File

@@ -24,7 +24,8 @@ intents = disnake.Intents(messages=True,
bot = commands.Bot(command_prefix=determine_prefix, bot = commands.Bot(command_prefix=determine_prefix,
intents=intents, intents=intents,
reload=True reload=True,
) )
@@ -34,6 +35,7 @@ asyncio.run(work_with_cogs('load', bot, asyncio.run(cog_list())))
@bot.event @bot.event
async def on_ready(): async def on_ready():
logger.info(f'Bot started') logger.info(f'Bot started')
logger.info(f'Disnake version {disnake.__version__}')
logger.info('We have logged in as {0.user}'.format(bot)) logger.info('We have logged in as {0.user}'.format(bot))
logger.info(f'Version of bot is - v{ver.major}.{ver.minor}.{ver.micro}-{ver.releaselevel}') logger.info(f'Version of bot is - v{ver.major}.{ver.minor}.{ver.micro}-{ver.releaselevel}')
@@ -47,13 +49,7 @@ async def on_ready():
description="Specify what do with cogs", description="Specify what do with cogs",
type=OptionType.string, type=OptionType.string,
required=True, required=True,
choices=[ choices=["load", "unload", "reload", "enable", "disable"]
OptionChoice("load", "load"),
OptionChoice("unload", "unload"),
OptionChoice("reload", "reload"),
OptionChoice("enable", "enable"),
OptionChoice("disable", "disable"),
]
), ),
Option( Option(
'cog', 'cog',
@@ -63,22 +59,19 @@ async def on_ready():
] ]
) )
@commands.is_owner() @commands.is_owner()
async def slash_cogs(inter, what_do, cog: str = asyncio.run(cog_list())) -> None: async def slash_cogs(inter: disnake.ApplicationCommandInteraction, what_do, cog: str):
await work_with_cogs(what_do, bot, cog) await work_with_cogs(what_do, bot, cog)
await inter.response.send_message(f'Cog {cog} is {what_do}ed', ephemeral=True) await inter.response.send_message(f'Cog {cog} is {what_do}ed', ephemeral=True)
@slash_cogs.autocomplete('cog') @slash_cogs.autocomplete('cog')
async def _cog_opt(inter: disnake.ApplicationCommandInteraction, current: str, what_do) -> List[OptionChoice]: async def _cog_opt(inter: disnake.ApplicationCommandInteraction, current: str, what_do):
_what = ['load', 'reload', 'unload', 'disable'] current = current.lower()
if what_do in _what: if what_do == 'enable':
_list = await cog_list()
elif what_do == 'enable':
_list = await cog_list('./cogs/disabled/') _list = await cog_list('./cogs/disabled/')
return [ else:
OptionChoice(name=choice, value=choice) _list = await cog_list()
for choice in _list if current.lower() in choice.lower() return [choice for choice in _list if current in choice.lower()]
]
@slash_cogs.error @slash_cogs.error

View File

@@ -129,6 +129,7 @@ class Admin(commands.Cog, name='Admin'):
@slash_set_prefix.error @slash_set_prefix.error
async def set_prefix_error(self, inter, prefix): async def set_prefix_error(self, inter, prefix):
await inter.response.send_message("You don`t have permissions", ephemeral=True) await inter.response.send_message("You don`t have permissions", ephemeral=True)
logger.error(prefix)
@commands.has_permissions(administrator=True) @commands.has_permissions(administrator=True)
@commands.slash_command( @commands.slash_command(
@@ -140,7 +141,7 @@ class Admin(commands.Cog, name='Admin'):
) )
async def set_time(self, async def set_time(self,
inter: disnake.ApplicationCommandInteraction, inter: disnake.ApplicationCommandInteraction,
seconds: commands.Range[5, 30]): seconds: commands.Range[int, 5, 30]):
await write_json(inter.guild.id, "seconds", seconds) await write_json(inter.guild.id, "seconds", seconds)
await inter.response.send_message(f"Change max audio duration to {seconds} sec", ephemeral=True) await inter.response.send_message(f"Change max audio duration to {seconds} sec", ephemeral=True)
@@ -148,22 +149,19 @@ class Admin(commands.Cog, name='Admin'):
@commands.slash_command( @commands.slash_command(
name="set_bot_channel", name="set_bot_channel",
description="Set channel which iterate with bot", description="Set channel which iterate with bot",
options=[
Option("channel", "specify channel", OptionType.string, required=True),
]
) )
async def set_bot_channel(self, inter, channel): async def set_bot_channel(self, inter, channel: str):
print(type(inter.guild.text_channels)) await write_json(inter.guild.id,
await write_json(inter.guild.id, "channel", channel.id) "channel",
await inter.response.send_message(f"Channel set up to {channel.mention}", ephemeral=True) disnake.utils.find(lambda d: d.name == channel, inter.guild.channels).id)
await inter.response.send_message(f"Channel set up to {channel}", ephemeral=True)
@set_bot_channel.autocomplete('channel') @set_bot_channel.autocomplete('channel')
async def _list_text_channels(self, async def _list_text_channels(self,
inter: disnake.ApplicationCommandInteraction, inter: disnake.ApplicationCommandInteraction,
current: str) -> List[OptionChoice]: current: str) -> List[OptionChoice]:
_list = [] _list = [r.name for r in inter.guild.text_channels]
for _channel in inter.guild.text_channels:
_list.append(_channel)
return [ return [
OptionChoice(name=choice, value=choice) OptionChoice(name=choice, value=choice)
for choice in _list if current in choice for choice in _list if current in choice

View File

@@ -1,11 +1,13 @@
import random import random
from os import path, makedirs, rename, remove from itertools import islice
from typing import List
import disnake
from disnake import OptionChoice, Option, OptionType
from disnake.ext import commands from disnake.ext import commands
from lib import logger from lib import logger, ListGenerator
from lib import determine_time from lib import read_db
from lib import read_db, check_exist_audio, add_audio
from lib import play_audio from lib import play_audio
@@ -29,80 +31,52 @@ class Audio(commands.Cog, name='Audio'):
from lib.Comands import read_json from lib.Comands import read_json
_role = await read_json(member.guild.id, 'tigger_role') _role = await read_json(member.guild.id, 'tigger_role')
# Read audio from DB # Read audio from DB
audio_db = await read_db(member.guild.id, member.id, 'usertracks') audio_db = await read_db(member.guild.id, member.id, 'defaulttracks')
def_audio_db = await read_db(member.guild.id, member.id, 'defaulttracks')
if audio_db is not None:
audio_db = audio_db.split(', ') # Need to fix creating list
for i in range(len(audio_db)):
audio_db[i] = f'{member.id}/{audio_db[i]}'
if def_audio_db is not None:
def_audio_db = def_audio_db.split(', ')
from lib.Comands import list_files
def_audio_ls = await list_files()
if def_audio_db or audio_db is not None: if audio_db is not None:
if not def_audio_db: def_audio_db = [] audio = audio_db.split(', ')
if not audio_db: audio_db = [] else:
from lib.Comands import list_files
audio = await list_files()
if audio_db is not None:
logger.info(f'Play audio from DB') logger.info(f'Play audio from DB')
full_audio = def_audio_db + audio_db await play_audio(f'audio/{random.choice(audio)}', self.bot, after.channel)
await play_audio(f'audio/{random.choice(full_audio)}', self.bot, after.channel)
elif len(member.roles) == 1 or _role is None: elif len(member.roles) == 1 or _role is None:
logger.info(f'Skip playing by role') logger.info(f'Skip playing by role')
elif any(str(role.id) in _role for role in member.roles): elif any(str(role.id) in _role for role in member.roles):
logger.info(f'Play audio from list by role') logger.info(f'Play audio from list by role')
await play_audio(f'audio/{random.choice(def_audio_ls)}', self.bot, after.channel) await play_audio(f'audio/{random.choice(audio)}', self.bot, after.channel)
else: else:
logger.info(f'Skip playing by any else') logger.info(f'Skip playing by any else')
@commands.command(name="upload_audio", @commands.slash_command(name="play_audio",
description=f"Add audio to bot") description="Make possible playing audio by command",
async def upload_audio(self, ctx, user=None): options=[
user = user or ctx.author Option(name="audio",
if ctx.author.guild_permissions.administrator or user is ctx.author: type=OptionType.string,
if ctx.message.attachments: required=True
from os import error )
if not path.isdir(f'tmp/{user.id}'): ])
try: async def playaudio(self, inter: disnake.ApplicationCommandInteraction,
makedirs(f'tmp/{user.id}') audio: str
except error as _error: ):
pass if inter.author.voice is not None:
await inter.response.send_message(f'Played {audio}', ephemeral=True)
await play_audio(audio, self.bot, inter.author.voice.channel)
else:
await inter.response.send_message('You`re not in voice', ephemeral=True)
if not path.isdir(f'audio/{user.id}'): @playaudio.autocomplete('audio')
try: async def list_to_play(self, inter: disnake.ApplicationCommandInteraction, current: str):
makedirs(f'audio/{user.id}') current = current.lower()
except error as _error: _dict: dict = {}
pass for f in ListGenerator('audio'):
for at in ctx.message.attachments: _dict[f.name] = f'{f.path}/{f.name}'
import mimetypes return [
OptionChoice(name=choice, value=f'{_dict[choice]}')
await at.save(f'tmp/{user.id}/{at.filename}') for choice in _dict if current in choice.lower()
guess = mimetypes.guess_type(f'tmp/{user.id}/{at.filename}') ]
if guess[0].split('/')[0] == 'audio':
from pymediainfo import MediaInfo
file = f'tmp/{user.id}/{at.filename}'
duration = round(MediaInfo.parse(file).tracks[0].duration / 1000)
max_duration = int(determine_time(ctx))
print(type(max_duration))
if duration > max_duration:
await ctx.reply(f'Audio duration is {duration}, but max is {max_duration}')
remove(f'tmp/{user.id}/{at.filename}')
else:
a = await read_db(ctx.guild.id, user.id, 'usertracks')
if a:
audiolist = a + ", " + f'{at.filename}'
else:
audiolist = f'{at.filename}'
await check_exist_audio(ctx, ctx.guild.id, user.id, 'usertracks', at.filename)
await add_audio(ctx.guild.id, user.id, audiolist)
rename(f'tmp/{user.id}/{at.filename}', f'audio/{user.id}/{at.filename}')
elif guess[0].split('/')[0] != 'audio':
await ctx.reply(f'It not audio {at.filename}\n it`s {guess[0]}')
remove(f'tmp/{user.id}/{at.filename}')
else:
await ctx.reply("Has no Attachment")
else:
await ctx.reply(f'You`re not admin. You can add audio only for your own account')
def setup(bot): # an extension must have a setup function def setup(bot): # an extension must have a setup function

33
cogs/disabled/test.py Normal file
View File

@@ -0,0 +1,33 @@
from typing import List
import disnake
from disnake import OptionChoice
from disnake.ext import commands
from lib import logger
class Testing(commands.Cog, name='Testing'):
def __init__(self, bot):
self.bot = bot # defining bot as global var in class
@commands.Cog.listener() # this is a decorator for events/listeners
async def on_ready(self):
logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
@commands.slash_command(
name='select_audio',
description='Select Audios from List'
)
async def select_audio(self, inter, audios: str):
pass
@select_audio.autocomplete('audios')
async def _list_audios(self,
inter: disnake.ApplicationCommandInteraction,
current: str) -> List[OptionChoice]:
pass
def setup(bot): # an extension must have a setup function
bot.add_cog(Testing(bot)) # adding a cog

View File

@@ -1,9 +1,8 @@
import disnake import disnake
from disnake import Option, OptionType, Colour from disnake import Option, OptionType, Colour
from disnake.ext import commands from disnake.ext import commands
from lib import DB_Reader from lib import DBReader
from lib import logger from lib import logger
@@ -23,30 +22,24 @@ class General(commands.Cog):
] ]
) )
async def info(self, inter, user=None): async def info(self, inter, user=None):
user_audio = None audio = None
default_audio = None
user = user or inter.author user = user or inter.author
_user = DB_Reader(inter.guild.id) _user = DBReader(inter.guild.id)
for r in _user: for r in _user:
if r.userid == user.id: if r.userid == user.id:
user_audio = r.usertracks audio = r.defaulttracks
default_audio = r.defaulttracks
rolelist = [r.mention for r in user.roles if r != inter.guild.default_role] rolelist = [r.mention for r in user.roles if r != inter.guild.default_role]
if rolelist: if rolelist:
roles = "\n".join(rolelist) roles = "\n".join(rolelist)
else: else:
roles = "Not added any role" roles = "Not added any role"
if user_audio:
audios = "" + "\n".join(sorted(user_audio.split(", "))) if audio:
audios = "" + "\n".join(sorted(audio.split(", ")))
else: else:
audios = "Not selected audio" audios = "Not selected audio"
if default_audio:
audios2 = "" + "\n".join(sorted(default_audio.split(", ")))
else:
audios2 = "Not selected audio"
emb = disnake.Embed( emb = disnake.Embed(
title=f"General information", title=f"General information",
description=f"General information on server about {user}", description=f"General information on server about {user}",
@@ -57,8 +50,7 @@ class General(commands.Cog):
value=f"Username: {user}\n" value=f"Username: {user}\n"
f"Nickname: {user.nick}\n" f"Nickname: {user.nick}\n"
f"Joined at: {user.joined_at.strftime('%A, %B %d %Y @ %H:%M:%S')}", inline=False) f"Joined at: {user.joined_at.strftime('%A, %B %d %Y @ %H:%M:%S')}", inline=False)
emb.add_field(name="User audio list", value=f"{audios}", inline=True) emb.add_field(name="Default audio list", value=f"{audios}", inline=True)
emb.add_field(name="Default audio list", value=f"{audios2}", inline=True)
emb.add_field(name="Roles list", value=f"{roles}", inline=True) emb.add_field(name="Roles list", value=f"{roles}", inline=True)
emb.set_footer(text="Information requested by: {}".format(inter.author.display_name)) emb.set_footer(text="Information requested by: {}".format(inter.author.display_name))

View File

@@ -33,7 +33,7 @@ class BotInfo(commands.Cog, name='Bot Info'):
f'Prefix: `{determine_prefix(self.bot, inter)}\n`' f'Prefix: `{determine_prefix(self.bot, inter)}\n`'
f"Max audio duration: {determine_time(inter)} sec\n" f"Max audio duration: {determine_time(inter)} sec\n"
) )
emb.add_field(name="Bot info:", value=f"Bot owner: <@{self.bot.owner_id}>\n" emb.add_field(name="Bot info:", value=f"Bot owner: <@386629192743256065>\n"
f"Bot version: {ver.major}.{ver.minor}.{ver.micro}-{ver.releaselevel}") f"Bot version: {ver.major}.{ver.minor}.{ver.micro}-{ver.releaselevel}")
emb.set_footer(text="Information requested by: {}".format(inter.author.display_name)) emb.set_footer(text="Information requested by: {}".format(inter.author.display_name))

View File

@@ -1,67 +0,0 @@
from typing import List
import disnake
from disnake import Option, OptionType, OptionChoice
from disnake.ext import commands
from lib import ListGenerator
from lib import logger
from lib import play_audio
class Testing(commands.Cog, name='Testing'):
def __init__(self, bot):
self.bot = bot # defining bot as global var in class
@commands.Cog.listener() # this is a decorator for events/listeners
async def on_ready(self):
logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
@commands.slash_command(name="play_audio",
description="Make possible playing audio by command",
options=[
Option(name="audio",
type=OptionType.string,
required=True
)
])
async def playaudio(self, inter: disnake.ApplicationCommandInteraction,
audio: str
):
if inter.author.voice is not None:
await inter.response.send_message(f'Played {audio}', ephemeral=True)
await play_audio(audio, self.bot, inter.author.voice.channel)
else:
await inter.response.send_message('You`re not in voice', ephemeral=True)
@playaudio.autocomplete('audio')
async def list_to_play(self, inter: disnake.ApplicationCommandInteraction, current: str) -> List[OptionChoice]:
_def_iter = ListGenerator('audio')
_def_dict: dict = {}
for f in _def_iter:
_def_dict[f.name] = f'{f.path}/{f.name}'
_user_dict: dict = {}
try:
_user_iter = ListGenerator(f'audio/{inter.author.id}')
for f in _user_iter:
_user_dict[f.name] = f'{f.path}/{f.name}'
# user_dict = []
# for _track in user_list:
except IndexError:
pass
_dict = {}
_dict.update(_def_dict)
_dict.update(_user_dict)
return [
OptionChoice(name=choice, value=f'{_dict[choice]}')
for choice in _dict if current.lower() in choice.lower()
]
def setup(bot): # an extension must have a setup function
bot.add_cog(Testing(bot)) # adding a cog

View File

@@ -4,7 +4,7 @@ import sqlite3
from lib import logger from lib import logger
class DB_Reader: class DBReader:
def __init__(self, guildid: int = None): def __init__(self, guildid: int = None):
self._guildid = guildid self._guildid = guildid

View File

@@ -1,6 +1,5 @@
import mimetypes import mimetypes
import os import os
from typing import Tuple, Optional
class ListGenerator: class ListGenerator:
@@ -36,10 +35,10 @@ class ListGenerator:
class _FileAttrs: class _FileAttrs:
def __init__(self, name, path, type, exc): def __init__(self, name, path, mimetype, exc):
self.name = name self.name = name
self.path = path self.path = path
self.mimetype = type self.mimetype = mimetype
self.exc = exc self.exc = exc
def __str__(self): def __str__(self):
@@ -63,7 +62,7 @@ class _ListGenerationIter:
return self return self
@property @property
def type(self) -> tuple[Optional[str], Optional[str]]: def type(self) -> str:
guess = mimetypes.guess_type(f'{self._path}/{self._list[self._current_index]}')[0] guess = mimetypes.guess_type(f'{self._path}/{self._list[self._current_index]}')[0]
return guess return guess
@@ -82,6 +81,6 @@ class _ListGenerationIter:
_type = self.type _type = self.type
_exc = self._exc _exc = self._exc
self._current_index += 1 self._current_index += 1
memb = _FileAttrs(_name, _path, _type, _exc) _memb = _FileAttrs(_name, _path, _type, _exc)
return memb return _memb
raise StopIteration raise StopIteration

View File

@@ -1,16 +1,16 @@
from .Logger import logger from .Logger import logger
from asyncio import sleep from asyncio import sleep
from disnake import FFmpegPCMAudio from disnake import FFmpegOpusAudio, opus
async def play_audio(audio, bot, vc): async def play_audio(audio, bot, vc):
if not bot.voice_clients: if not bot.voice_clients:
logger.info(audio) # logger.info(audio)
logger.error(f'Playing: {audio}') logger.error(f'Playing: {audio}')
await sleep(1) await sleep(1)
vp = await vc.connect() vp = await vc.connect()
if not vp.is_playing(): if not vp.is_playing():
vp.play(FFmpegPCMAudio(f'{audio}'), after=None) vp.play(FFmpegOpusAudio(f'{audio}', executable='ffmpeg'), after=lambda e: print('done', e))
while vp.is_playing(): while vp.is_playing():
await sleep(0.5) await sleep(0.5)
await sleep(1) await sleep(1)

80
main.py Normal file
View File

@@ -0,0 +1,80 @@
import random
import sys
import threading
import logging
import discord
from asyncio import sleep
from os import walk
from discord import user, member
from discord import FFmpegPCMAudio
from discord.ext import commands
threading.current_thread().name = "main"
logging.basicConfig(stream=sys.stdout, filemode='w', level='INFO',
format='%(asctime)s - %(levelname)s - %(threadName)s - %(message)s')
intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix='$', guild_subscriptions=True, intents=intents)
f = []
for filenames in walk('audio'):
f.extend(filenames)
break
f = f[2]
@bot.event
async def on_voice_state_update(member, before, after):
# channel = bot.get_channel(783729824896122930)
_role = 929729495370461205
_memb = 375664768087752714
_bot_id = 946819004314570852
role = discord.utils.find(lambda r: r.name == 'тарковчане', member.roles)
if before.channel is None and role in member.roles:
track = random.randint(0, len(f) - 1)
audio_source = FFmpegPCMAudio(f'audio/{f[track]}')
logging.error(f'{track}\t\t{f[track]}')
if not bot.voice_clients:
await sleep(1)
_channel = after.channel
vc = await after.channel.connect()
if not vc.is_playing():
vc.play(audio_source, after=None)
while vc.is_playing():
await sleep(0.5)
await sleep(1)
await vc.disconnect()
if before.channel is None and member.id == _memb:
track = random.randint(0, len(f) - 1)
audio_source = FFmpegPCMAudio(f'audio/{_memb}/bear2_enemy_scav3.wav')
logging.error(f'{track}\t\t\t{f[track]}')
if not bot.voice_clients:
await sleep(1)
_channel = after.channel
vc = await after.channel.connect()
if not vc.is_playing():
vc.play(audio_source, after=None)
while vc.is_playing():
await sleep(0.5)
await sleep(1)
await vc.disconnect()
@bot.event
async def on_member_join(member):
if member.bot == 0:
role = discord.utils.get(member.guild.roles, id=734358428939452486)
else:
role = discord.utils.get(member.guild.roles, id=734358434945826858)
logging.info(f"Adding to {member} role {role}")
await member.add_roles(role)
@bot.event
async def on_ready():
logging.info(f'Bot started')
bot.run('OTQ2ODE5MDA0MzE0NTcwODUy.YhkP6Q.dhFqi2MJMrxzHt5FtjK5Cl-5BI8')

View File

@@ -1,6 +1,6 @@
disnake[audio]~=2.5.2 disnake[audio]==2.8.0
psutil==5.9.2 psutil==5.9.4
pymediainfo~=5.1.0 pymediainfo==6.0.1
pyNaCl~=1.5.0 pyNaCl~=1.5.0
python-dotenv==0.21.0 python-dotenv==1.0.0
ffmpeg-python~=0.2.0 ffmpeg-python~=0.2.0

15
setup.py Normal file
View File

@@ -0,0 +1,15 @@
from setuptools import setup
import __init__
setup(
name='fun and admin bot',
version=__init__.__version__,
packages=['lib'],
url='',
platforms='POSIX',
license='',
author='riksl',
author_email='',
description='',
requires=[]
)

5
test.py Normal file
View File

@@ -0,0 +1,5 @@
from lib import ListGenerator
for i in ListGenerator('audio'):
print(i.__repr__())
print(f"{i.path}/{i.name}")