updated structure

This commit is contained in:
bacon
2024-03-17 22:03:27 +03:00
parent 4e535f6580
commit d22c3ca6b6
44 changed files with 955 additions and 948 deletions

10
.gitignore vendored
View File

@@ -1,12 +1,10 @@
/tmp/ /tmp/
/audio/*/ audio/*/
/.idea /.idea
/user.db user.db
*.pyc *.pyc
/.run/ /.run/
/.env .env
*.exe *.exe
/venv/ /venv/
/fun_and_admin_bot.egg-info/ config.json
/.YMcache/
config.json

View File

@@ -24,8 +24,12 @@ unittest:
- test - test
before_script: before_script:
- cd $CI_PROJECT_DIR - cd $CI_PROJECT_DIR
- pip install python-venv
- python -m venv venv
- chmod u+x venv/bin/activate
- source venv/bin/activate
- pip install -r requirements.txt - pip install -r requirements.txt
- pip install pytest-asyncio - cd tests
script: script:
- pytest -v - pytest -v

View File

@@ -1,16 +1,16 @@
__version__ = '0.0.7' __version__ = '0.0.7'
__title__ = "Pisya_bot" __title__ = "Pisya_bot"
__author__ = "baconborn" __author__ = "baconborn"
from typing import NamedTuple, Literal from typing import NamedTuple, Literal
class VersionInfo(NamedTuple): class VersionInfo(NamedTuple):
major: int major: int
minor: int minor: int
micro: int micro: int
releaselevel: Literal["alpha", "beta", "candidate", "final"] releaselevel: Literal["alpha", "beta", "candidate", "final"]
serial: int serial: int
version_info: VersionInfo = VersionInfo(major=0, minor=0, micro=7, releaselevel="alpha", serial=0) version_info: VersionInfo = VersionInfo(major=0, minor=0, micro=7, releaselevel="alpha", serial=0)

318
bot.py → bot/bot.py Executable file → Normal file
View File

@@ -1,159 +1,159 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import asyncio import asyncio
from os import getenv from os import getenv
from os.path import isfile from os.path import isfile
from disnake import OptionType, Option, Localized, ApplicationCommandInteraction, Intents, __version__ from disnake import OptionType, Option, Localized, ApplicationCommandInteraction, Intents, __version__
from disnake.ext.commands import Bot, is_owner from disnake.ext.commands import Bot, is_owner
from dotenv import load_dotenv from dotenv import load_dotenv
from lib.CogsPrep import work_with_cogs, cog_list from lib.CogsPrep import work_with_cogs, cog_list
from lib.Comands import determine_prefix from lib.Comands import determine_prefix
from lib.Logger import logger from lib.Logger import logger
load_dotenv() load_dotenv()
if not isfile('.env') or not getenv('CONF_FILE'): if not isfile('.env') or not getenv('CONF_FILE'):
with open('.env', 'a', encoding='utf-8') as f: with open('.env', 'a', encoding='utf-8') as f:
f.write("CONF_FILE='config.json'\n") f.write("CONF_FILE='config.json'\n")
load_dotenv() load_dotenv()
if not isfile(getenv('CONF_FILE')): if not isfile(getenv('CONF_FILE')):
with open(getenv('CONF_FILE'), 'a', encoding='utf-8') as f: with open(getenv('CONF_FILE'), 'a', encoding='utf-8') as f:
f.write("") f.write("")
intents = Intents(messages=True, intents = Intents(messages=True,
guilds=True, guilds=True,
message_content=True, message_content=True,
voice_states=True, voice_states=True,
members=True, members=True,
presences=True presences=True
) )
bot = Bot(command_prefix=determine_prefix, bot = Bot(command_prefix=determine_prefix,
intents=intents, intents=intents,
reload=True, reload=True,
test_guilds=[648126669122568215] test_guilds=[648126669122568215]
) )
bot.i18n.load("locale/") bot.i18n.load("locale/")
asyncio.run(work_with_cogs('load', bot, cog_list())) asyncio.run(work_with_cogs('load', bot, cog_list()))
@bot.event @bot.event
async def on_ready(): async def on_ready():
logger.info('Bot started') logger.info('Bot started')
logger.info(f'Disnake version {__version__}') logger.info(f'Disnake version {__version__}')
logger.info(f'We have logged in as {bot.user}') logger.info(f'We have logged in as {bot.user}')
@bot.slash_command( @bot.slash_command(
name='cog', name='cog',
options=[ options=[
Option( Option(
name=Localized('cog', key="COG".lower()), name=Localized('cog', key="COG".lower()),
description=Localized("cog file", key="COG_FILE"), description=Localized("cog file", key="COG_FILE"),
type=OptionType.string type=OptionType.string
) )
] ]
) )
@is_owner() @is_owner()
async def slash_cogs(inter: ApplicationCommandInteraction): async def slash_cogs(inter: ApplicationCommandInteraction):
""" """
Working with cogs (modules) {{SLASH_COG}} Working with cogs (modules) {{SLASH_COG}}
Parameters Parameters
---------- ----------
:param inter: :param inter:
""" """
pass pass
@slash_cogs.sub_command(description=Localized("Enables Cog", key="ENABLE_COG")) @slash_cogs.sub_command(description=Localized("Enables Cog", key="ENABLE_COG"))
async def enable(inter: ApplicationCommandInteraction, cog: str): async def enable(inter: ApplicationCommandInteraction, cog: str):
""" """
Parameters Parameters
---------- ----------
:param inter: :param inter:
:param cog: Select Cogfile {{COG_FILE}} :param cog: Select Cogfile {{COG_FILE}}
""" """
await work_with_cogs('enable', bot, cog) await work_with_cogs('enable', bot, cog)
await inter.response.send_message(f'Cog {cog} is enabled', ephemeral=True) await inter.response.send_message(f'Cog {cog} is enabled', ephemeral=True)
@slash_cogs.sub_command(description=Localized("Disables Cog", key="DISABLE_COG")) @slash_cogs.sub_command(description=Localized("Disables Cog", key="DISABLE_COG"))
async def disable(inter: ApplicationCommandInteraction, cog: str): async def disable(inter: ApplicationCommandInteraction, cog: str):
""" """
Parameters Parameters
---------- ----------
:param inter: :param inter:
:param cog: Select Cogfile {{COG_FILE}} :param cog: Select Cogfile {{COG_FILE}}
""" """
await work_with_cogs('disable', bot, cog) await work_with_cogs('disable', bot, cog)
await inter.response.send_message(f'Cog {cog} is disabled', ephemeral=True) await inter.response.send_message(f'Cog {cog} is disabled', ephemeral=True)
@slash_cogs.sub_command(description=Localized("Loads Cog", key="LOAD_COG")) @slash_cogs.sub_command(description=Localized("Loads Cog", key="LOAD_COG"))
async def load(inter: ApplicationCommandInteraction, cog: str): async def load(inter: ApplicationCommandInteraction, cog: str):
""" """
Parameters Parameters
---------- ----------
:param inter: :param inter:
:param cog: Select Cogfile {{COG_FILE}} :param cog: Select Cogfile {{COG_FILE}}
""" """
await work_with_cogs('load', bot, cog) await work_with_cogs('load', bot, cog)
await inter.response.send_message(f'Cog {cog} is loaded', ephemeral=True) await inter.response.send_message(f'Cog {cog} is loaded', ephemeral=True)
@slash_cogs.sub_command(description=Localized("Unload Cog", key="UNLOAD_COG")) @slash_cogs.sub_command(description=Localized("Unload Cog", key="UNLOAD_COG"))
async def unload(inter: ApplicationCommandInteraction, cog: str): async def unload(inter: ApplicationCommandInteraction, cog: str):
""" """
Parameters Parameters
---------- ----------
:param inter: :param inter:
:param cog: Select Cogfile {{COG_FILE}} :param cog: Select Cogfile {{COG_FILE}}
""" """
await work_with_cogs('unload', bot, cog) await work_with_cogs('unload', bot, cog)
await inter.response.send_message(f'Cog {cog} is unload', ephemeral=True) await inter.response.send_message(f'Cog {cog} is unload', ephemeral=True)
@slash_cogs.sub_command(description=Localized("Reloads Cog", key="RELOAD_COG")) @slash_cogs.sub_command(description=Localized("Reloads Cog", key="RELOAD_COG"))
async def reload(inter: ApplicationCommandInteraction, cog: str): async def reload(inter: ApplicationCommandInteraction, cog: str):
""" """
Parameters Parameters
---------- ----------
:param inter: :param inter:
:param cog: Select Cogfile {{COG_FILE}} :param cog: Select Cogfile {{COG_FILE}}
""" """
await work_with_cogs('reload', bot, cog) await work_with_cogs('reload', bot, cog)
await inter.response.send_message(f'Cog {cog} is reloaded', ephemeral=True) await inter.response.send_message(f'Cog {cog} is reloaded', ephemeral=True)
@disable.autocomplete('cog') @disable.autocomplete('cog')
@unload.autocomplete('cog') @unload.autocomplete('cog')
@load.autocomplete('cog') @load.autocomplete('cog')
@reload.autocomplete('cog') @reload.autocomplete('cog')
async def _cog_opt(inter: ApplicationCommandInteraction, current: str): async def _cog_opt(inter: ApplicationCommandInteraction, current: str):
current = current.lower() current = current.lower()
_list = await cog_list(fold='./cogs/') _list = cog_list(fold='./cogs/')
return [choice for choice in _list if current in choice.lower()] return [choice for choice in _list if current in choice.lower()]
@enable.autocomplete('cog') @enable.autocomplete('cog')
async def _cog_opt(inter: ApplicationCommandInteraction, current: str): async def _cog_opt(inter: ApplicationCommandInteraction, current: str):
current = current.lower() current = current.lower()
_list = await cog_list(fold='./cogs/disabled/') _list = cog_list(fold='./cogs/disabled/')
return [choice for choice in _list if current in choice.lower()] return [choice for choice in _list if current in choice.lower()]
@slash_cogs.error @slash_cogs.error
async def cogs_error(inter: ApplicationCommandInteraction): async def cogs_error(inter: ApplicationCommandInteraction):
await inter.response.send_message(Localized("Error", key="EROR"), ephemeral=True) await inter.response.send_message(Localized("Error", key="EROR"), ephemeral=True)
logger.error(f'User {inter.author} tries to use cogs func') logger.error(f'User {inter.author} tries to use cogs func')
bot.run(getenv('TOKEN')) bot.run(getenv('TOKEN'))

View File

@@ -1,148 +1,148 @@
from asyncio import sleep from asyncio import sleep
import disnake import disnake
from disnake import Option, OptionType, Localized from disnake import Option, OptionType, Localized
from disnake.ext import commands, tasks from disnake.ext import commands, tasks
from lib.Comands import read_json, write_json from bot.lib.Comands import read_json, write_json
from lib.DB_Worker import fill_bd, prepare_db, work_with_db from bot.lib.DB_Worker import fill_bd, prepare_db, work_with_db
from lib.Logger import logger from bot.lib.Logger import logger
class Admin(commands.Cog, name='Admin'): class Admin(commands.Cog, name='Admin'):
def __init__(self, bot: commands.Bot): def __init__(self, bot: commands.Bot):
self.bot = bot # a defining bot as global var in class self.bot = bot # a defining bot as global var in class
@commands.Cog.listener() # this is a decorator for events/listeners @commands.Cog.listener() # this is a decorator for events/listeners
async def on_ready(self): async def on_ready(self):
for g in self.bot.get_all_members(): for g in self.bot.get_all_members():
await prepare_db(g.guild.id) await prepare_db(g.guild.id)
for g in self.bot.get_all_members(): for g in self.bot.get_all_members():
await fill_bd(g.name, g.id, g.bot, g.nick, g.guild.id) await fill_bd(g.name, g.id, g.bot, g.nick, g.guild.id)
self.activity.start() self.activity.start()
logger.info(f'Cog {__name__.split(".")[1]} is ready!.') logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
@tasks.loop(seconds=20) @tasks.loop(seconds=20)
async def activity(self): async def activity(self):
await self.bot.change_presence( await self.bot.change_presence(
activity=disnake.Activity( activity=disnake.Activity(
name=f'at users: {str(len(self.bot.users))}', name=f'at users: {str(len(self.bot.users))}',
type=3 type=3
) )
) )
await sleep(10) await sleep(10)
await self.bot.change_presence( await self.bot.change_presence(
activity=disnake.Activity( activity=disnake.Activity(
name=f'at servers: {str(len(self.bot.guilds))}', name=f'at servers: {str(len(self.bot.guilds))}',
type=3 type=3
) )
) )
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_update(self, before: disnake.Member, after: disnake.Member): async def on_member_update(self, before: disnake.Member, after: disnake.Member):
sql_update_query = f"""UPDATE "{after.guild.id}" set nick = ? where userid = ?""" sql_update_query = f"""UPDATE "{after.guild.id}" set nick = ? where userid = ?"""
data_tuple = (after.nick, before.id) data_tuple = (after.nick, before.id)
await work_with_db(sql_update_query, data_tuple) await work_with_db(sql_update_query, data_tuple)
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_join(self, guild): async def on_guild_join(self, guild):
for g in guild.members: for g in guild.members:
await fill_bd(g.name, g.id, g.bot, g.nick, guild.id) await fill_bd(g.name, g.id, g.bot, g.nick, guild.id)
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member): async def on_member_join(self, member):
await fill_bd(member.name, member.id, member.bot, member.nick, member.guild.id) await fill_bd(member.name, member.id, member.bot, member.nick, member.guild.id)
bot_role = read_json(member.guild.id, 'bot_role') # Get bot role bot_role = read_json(member.guild.id, 'bot_role') # Get bot role
guest_role = read_json(member.guild.id, 'guest_role') # Get guest role guest_role = read_json(member.guild.id, 'guest_role') # Get guest role
if bot_role or guest_role: if bot_role or guest_role:
if member.bot == 0: if member.bot == 0:
role = disnake.utils.get(member.guild.roles, id=guest_role) role = disnake.utils.get(member.guild.roles, id=guest_role)
else: else:
role = disnake.utils.get(member.guild.roles, id=bot_role) role = disnake.utils.get(member.guild.roles, id=bot_role)
logger.info(f"Adding to {member} role {role}") logger.info(f"Adding to {member} role {role}")
await member.add_roles(role) await member.add_roles(role)
@commands.slash_command( @commands.slash_command(
name="set_default_role", name="set_default_role",
description=Localized("Set Default bot role", key="DEF_ROLE"), description=Localized("Set Default bot role", key="DEF_ROLE"),
options=[ options=[
Option("role", Option("role",
"Specify role", "Specify role",
OptionType.role, OptionType.role,
required=True), required=True),
] ]
) )
@commands.has_permissions(administrator=True) @commands.has_permissions(administrator=True)
async def set_guest_role(self, inter: disnake.ApplicationCommandInteraction, role): async def set_guest_role(self, inter: disnake.ApplicationCommandInteraction, role):
await write_json(inter.guild.id, "guest_role", role.id) await write_json(inter.guild.id, "guest_role", role.id)
await inter.response.send_message(f"Set up bot role to: `{role.name}`", ephemeral=True) await inter.response.send_message(f"Set up bot role to: `{role.name}`", ephemeral=True)
@commands.command(name="set_prefix") @commands.command(name="set_prefix")
@commands.has_permissions(administrator=True) @commands.has_permissions(administrator=True)
async def command_set_prefix(self, ctx, prefix: str): async def command_set_prefix(self, ctx, prefix: str):
await write_json(ctx.guild.id, "prefix", prefix) await write_json(ctx.guild.id, "prefix", prefix)
await ctx.reply(f"Prefix set to: `{prefix}`") await ctx.reply(f"Prefix set to: `{prefix}`")
@commands.guild_only() @commands.guild_only()
@commands.slash_command( @commands.slash_command(
name="set_prefix", name="set_prefix",
description="Setting up bot prefix", description="Setting up bot prefix",
options=[ options=[
Option("prefix", Option("prefix",
"Specify prefix", "Specify prefix",
OptionType.string, OptionType.string,
required=True), required=True),
] ]
) )
@commands.has_permissions(administrator=True) @commands.has_permissions(administrator=True)
async def slash_set_prefix(self, inter: disnake.ApplicationCommandInteraction, prefix: str): async def slash_set_prefix(self, inter: disnake.ApplicationCommandInteraction, prefix: str):
await write_json(inter.guild.id, "prefix", prefix) await write_json(inter.guild.id, "prefix", prefix)
await inter.response.send_message(f"Prefix set to: `{prefix}`", ephemeral=True) await inter.response.send_message(f"Prefix set to: `{prefix}`", ephemeral=True)
@commands.guild_only() @commands.guild_only()
@commands.has_permissions(administrator=True) @commands.has_permissions(administrator=True)
@commands.slash_command( @commands.slash_command(
name="set_trigger_role", name="set_trigger_role",
description=Localized("Setting up role to trigger bot", key="KEY_ROLE"), description=Localized("Setting up role to trigger bot", key="KEY_ROLE"),
options=[ options=[
Option("role", Option("role",
Localized("Specify role", key="SETUP_ROLE"), Localized("Specify role", key="SETUP_ROLE"),
OptionType.role, OptionType.role,
required=True), required=True),
] ]
) )
async def set_trigger_role(self, inter: disnake.ApplicationCommandInteraction, role): async def set_trigger_role(self, inter: disnake.ApplicationCommandInteraction, role):
await write_json(inter.guild.id, "tigger_role", role.id) await write_json(inter.guild.id, "tigger_role", role.id)
await inter.response.send_message(f"Role set to: `{role.name}`", ephemeral=True) await inter.response.send_message(f"Role set to: `{role.name}`", ephemeral=True)
@commands.slash_command( @commands.slash_command(
name="set_bot_role", name="set_bot_role",
description=Localized("Set bot role", key="BOT_ROLE"), description=Localized("Set bot role", key="BOT_ROLE"),
options=[ options=[
Option("role", Option("role",
Localized("Specify role", key="SETUP_ROLE"), Localized("Specify role", key="SETUP_ROLE"),
OptionType.role, OptionType.role,
required=True) required=True)
] ]
) )
@commands.guild_only() @commands.guild_only()
@commands.has_permissions(administrator=True) @commands.has_permissions(administrator=True)
async def set_bot_role(self, ctx, role): async def set_bot_role(self, ctx, role):
await write_json(ctx.guild.id, await write_json(ctx.guild.id,
"bot_role", "bot_role",
role.id) role.id)
await ctx.send(f"Set up bot role to: `{role.name}`", ephemeral=True) await ctx.send(f"Set up bot role to: `{role.name}`", ephemeral=True)
@set_bot_role.error @set_bot_role.error
@set_trigger_role.error @set_trigger_role.error
@slash_set_prefix.error @slash_set_prefix.error
async def set_prefix_error(self, inter: disnake.ApplicationCommandInteraction, prefix): async def set_prefix_error(self, inter: disnake.ApplicationCommandInteraction, 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) logger.error(prefix)
def setup(bot): # an extension must have a setup function def setup(bot): # an extension must have a setup function
bot.add_cog(Admin(bot)) # adding a cog bot.add_cog(Admin(bot)) # adding a cog

View File

@@ -1,74 +1,74 @@
import random import random
import disnake import disnake
from disnake import OptionChoice, Option, OptionType, Member, VoiceState from disnake import OptionChoice, Option, OptionType, Member, VoiceState
from disnake.ext import commands from disnake.ext import commands
from lib.Logger import logger from bot.lib.ListGenerator import ListGenerator
from lib.Player import play_audio from bot.lib.Logger import logger
from lib.ListGenerator import ListGenerator from bot.lib.Player import play_audio
class Audio(commands.Cog, name='Audio'): class Audio(commands.Cog, name='Audio'):
def __init__(self, bot: commands.Bot): def __init__(self, bot: commands.Bot):
self.bot = bot self.bot = bot
@commands.Cog.listener() @commands.Cog.listener()
async def on_ready(self): async def on_ready(self):
logger.info(f'Cog {__name__.split(".")[1]} is ready!.') logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
@commands.Cog.listener() @commands.Cog.listener()
async def on_voice_state_update(self, member: Member, async def on_voice_state_update(self, member: Member,
before: VoiceState, before: VoiceState,
after: VoiceState): after: VoiceState):
if before.channel is None and not member.bot: if before.channel is None and not member.bot:
logger.info(f'Coneccted {member.name} to {after.channel.name}') logger.info(f'Coneccted {member.name} to {after.channel.name}')
if any('Escape from Tarkov' in str(user.activity) for user in after.channel.members): if any('Escape from Tarkov' in str(user.activity) for user in after.channel.members):
logger.info('Skip playing by Game') logger.info('Skip playing by Game')
else: else:
# Prepare list of audio # Prepare list of audio
from lib.Comands import read_json from bot.lib.Comands import read_json
_role = await read_json(member.guild.id, 'tigger_role') _role = await read_json(member.guild.id, 'tigger_role')
audio: list = [] audio: list = []
for _a in ListGenerator('audio'): for _a in ListGenerator('audio'):
audio.append(_a.name) audio.append(_a.name)
if len(member.roles) == 1 or _role is None: if len(member.roles) == 1 or _role is None:
logger.info('Skip playing by role') logger.info('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('Play audio from list by role') logger.info('Play audio from list by role')
await play_audio(f'audio/{random.choice(audio)}', self.bot, after.channel) await play_audio(f'audio/{random.choice(audio)}', self.bot, after.channel)
else: else:
logger.info('Skip playing by any else') logger.info('Skip playing by any else')
@commands.slash_command(name="play_audio", @commands.slash_command(name="play_audio",
description="Make possible playing audio by command", description="Make possible playing audio by command",
options=[ options=[
Option(name="audio", Option(name="audio",
type=OptionType.string, type=OptionType.string,
required=True required=True
) )
]) ])
async def playaudio(self, inter: disnake.ApplicationCommandInteraction, async def playaudio(self, inter: disnake.ApplicationCommandInteraction,
audio: str audio: str
): ):
if inter.author.voice is not None: if inter.author.voice is not None:
await inter.response.send_message(f'Played {audio}', ephemeral=True) await inter.response.send_message(f'Played {audio}', ephemeral=True)
await play_audio(audio, self.bot, inter.author.voice.channel) await play_audio(audio, self.bot, inter.author.voice.channel)
else: else:
await inter.response.send_message('You`re not in voice', ephemeral=True) await inter.response.send_message('You`re not in voice', ephemeral=True)
@playaudio.autocomplete('audio') @playaudio.autocomplete('audio')
async def list_to_play(self, inter: disnake.ApplicationCommandInteraction, current: str): async def list_to_play(self, inter: disnake.ApplicationCommandInteraction, current: str):
current = current.lower() current = current.lower()
_dict: dict = {} _dict: dict = {}
for f in ListGenerator('audio'): for f in ListGenerator('audio'):
_dict[f.name] = f'{f.path}/{f.name}' _dict[f.name] = f'{f.path}/{f.name}'
return [ return [
OptionChoice(name=choice, value=f'{_dict[choice]}') OptionChoice(name=choice, value=f'{_dict[choice]}')
for choice in _dict if current in choice.lower() for choice in _dict if current in choice.lower()
] ]
def setup(bot): # an extension must have a setup function def setup(bot): # an extension must have a setup function
bot.add_cog(Audio(bot)) # adding a cog bot.add_cog(Audio(bot)) # adding a cog

View File

@@ -1,43 +1,43 @@
from typing import List from typing import List
import disnake import disnake
from disnake import OptionChoice from disnake import OptionChoice
from disnake.ext import commands from disnake.ext import commands
from lib.Comands import write_json from bot.lib import logger
from lib.Logger import logger from bot.lib import write_json
class Fun(commands.Cog, name='Fun'): class Fun(commands.Cog, name='Fun'):
def __init__(self, bot: commands.Bot): def __init__(self, bot: commands.Bot):
self.bot = bot # defining bot as global var in class self.bot = bot # defining bot as global var in class
@commands.Cog.listener() # this is a decorator for events/listeners @commands.Cog.listener() # this is a decorator for events/listeners
async def on_ready(self): async def on_ready(self):
logger.info(f'Cog {__name__.split(".")[1]} is ready!.') logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
@commands.has_permissions(administrator=True) @commands.has_permissions(administrator=True)
@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",
) )
async def set_bot_channel(self, inter: disnake.ApplicationCommandInteraction, channel: str): async def set_bot_channel(self, inter: disnake.ApplicationCommandInteraction, channel: str):
await write_json(inter.guild.id, await write_json(inter.guild.id,
"channel", "channel",
disnake.utils.find(lambda d: d.name == channel, inter.guild.channels).id) 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) 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 = [r.name for r in inter.guild.text_channels] _list = [r.name for r in inter.guild.text_channels]
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
] ]
def setup(bot): # an extension must have a setup function def setup(bot): # an extension must have a setup function
bot.add_cog(Fun(bot)) # adding a cog bot.add_cog(Fun(bot)) # adding a cog

View File

@@ -1,29 +1,29 @@
import disnake import disnake
from disnake import Option from disnake import Option
from disnake.ext import commands from disnake.ext import commands
from lib import YandexPlayer from bot.lib import YandexPlayer
from lib.Logger import logger from bot.lib import logger
class Testing(commands.Cog, name='Testing'): class Testing(commands.Cog, name='Testing'):
def __init__(self, bot: commands.Bot): def __init__(self, bot: commands.Bot):
self.bot = bot # defining bot as global var in class self.bot = bot # defining bot as global var in class
@commands.Cog.listener() # this is a decorator for events/listeners @commands.Cog.listener() # this is a decorator for events/listeners
async def on_ready(self): async def on_ready(self):
logger.info(f'Cog {__name__.split(".")[1]} is ready!.') logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
@commands.slash_command(name='play', description='play audio test from yandex.music', options=[ @commands.slash_command(name='play', description='play audio test from yandex.music', options=[
Option(name='search', Option(name='search',
description='seach track/artist', description='seach track/artist',
required=True), required=True),
]) ])
async def play(self, inter: disnake.ApplicationCommandInteraction, search: str): async def play(self, inter: disnake.ApplicationCommandInteraction, search: str):
# TODO add yandex_music player with queue, playlists # TODO add yandex_music player with queue, playlists
result = YandexPlayer.search(search) result = YandexPlayer.search(search)
await inter.response.send_message(result, ephemeral=True) await inter.response.send_message(result, ephemeral=True)
def setup(bot): # an extension must have a setup function def setup(bot): # an extension must have a setup function
bot.add_cog(Testing(bot)) # adding a cog bot.add_cog(Testing(bot)) # adding a cog

View File

@@ -1,59 +1,59 @@
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.Logger import logger from bot.lib.Logger import logger
class General(commands.Cog): class General(commands.Cog):
def __init__(self, bot: commands.Bot): def __init__(self, bot: commands.Bot):
self.bot = bot # defining bot as global var in class self.bot = bot # defining bot as global var in class
@commands.Cog.listener() # this is a decorator for events/listeners @commands.Cog.listener() # this is a decorator for events/listeners
async def on_ready(self): async def on_ready(self):
logger.info(f'Cog {__name__.split(".")[1]} is ready!.') logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
@commands.slash_command( @commands.slash_command(
name="info", name="info",
options=[ options=[
Option("user", Option("user",
"Specify any user", "Specify any user",
OptionType.user), OptionType.user),
] ]
) )
async def info(self, inter: disnake.ApplicationCommandInteraction, user=None): async def info(self, inter: disnake.ApplicationCommandInteraction, user=None):
""" """
Shows user info {{SLASH_INFO}} Shows user info {{SLASH_INFO}}
Parameters Parameters
---------- ----------
:param inter: :param inter:
:param user: :param user:
:return: :return:
""" """
user = user or inter.author user = user or inter.author
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"
emb = disnake.Embed( emb = disnake.Embed(
title="General information", title="General information",
description=f"General information on server about {user}", description=f"General information on server about {user}",
color=Colour.random() color=Colour.random()
) )
emb.set_thumbnail(url=user.display_avatar) emb.set_thumbnail(url=user.display_avatar)
emb.add_field(name="General info", emb.add_field(name="General info",
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="Roles list", value=f"{roles}") emb.add_field(name="Roles list", value=f"{roles}")
emb.set_footer(text=f"Information requested by: {inter.author.display_name}") emb.set_footer(text=f"Information requested by: {inter.author.display_name}")
await inter.response.send_message(embed=emb, ephemeral=True) await inter.response.send_message(embed=emb, ephemeral=True)
def setup(bot): # an extension must have a setup function def setup(bot): # an extension must have a setup function
bot.add_cog(General(bot)) # adding a cog bot.add_cog(General(bot)) # adding a cog

View File

@@ -1,44 +1,44 @@
import os import os
import disnake import disnake
import psutil import psutil
from disnake import ApplicationCommandInteraction from disnake import ApplicationCommandInteraction
from disnake.ext import commands from disnake.ext import commands
from __init__ import version_info as ver from bot.__init__ import version_info as ver
from lib.Comands import determine_prefix from bot.lib.Comands import determine_prefix
from lib.Logger import logger from bot.lib.Logger import logger
class BotInfo(commands.Cog, name='Bot Info'): class BotInfo(commands.Cog, name='Bot Info'):
def __init__(self, bot: commands.Bot): def __init__(self, bot: commands.Bot):
self.bot = bot # defining bot as global var in class self.bot = bot # defining bot as global var in class
@commands.Cog.listener() # this is a decorator for events/listeners @commands.Cog.listener() # this is a decorator for events/listeners
async def on_ready(self): async def on_ready(self):
logger.info(f'Cog {__name__.split(".")[1]} is ready!.') logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
@commands.slash_command(name="info_bot", @commands.slash_command(name="info_bot",
description='Shows general info about bot') # this is for making a command description='Shows general info about bot') # this is for making a command
async def info_bot(self, inter: ApplicationCommandInteraction): async def info_bot(self, inter: ApplicationCommandInteraction):
_pid = os.getpid() _pid = os.getpid()
_process = psutil.Process(_pid) _process = psutil.Process(_pid)
emb = disnake.Embed( emb = disnake.Embed(
title="General information", title="General information",
description="General information on about bot", description="General information on about bot",
) )
emb.set_thumbnail(self.bot.user.avatar.url) emb.set_thumbnail(self.bot.user.avatar.url)
emb.add_field(name="System info:", value=f"Memory Usage: {round(_process.memory_info().rss / 2 ** 20, 2)} Mb\n" emb.add_field(name="System info:", value=f"Memory Usage: {round(_process.memory_info().rss / 2 ** 20, 2)} Mb\n"
f"CPU Usage: {_process.cpu_percent()}%\n" f"CPU Usage: {_process.cpu_percent()}%\n"
f'Bot ping: {round(self.bot.latency * 1000)}\n' f'Bot ping: {round(self.bot.latency * 1000)}\n'
f'Prefix: `{determine_prefix(self.bot, inter)}\n`' f'Prefix: `{determine_prefix(self.bot, inter)}\n`'
) )
emb.add_field(name="Bot info:", value="Bot owner: <@386629192743256065>\n" emb.add_field(name="Bot info:", value="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=f"Information requested by: {inter.author.display_name}") emb.set_footer(text=f"Information requested by: {inter.author.display_name}")
await inter.response.send_message(embed=emb, ephemeral=True) await inter.response.send_message(embed=emb, ephemeral=True)
def setup(bot): # an extension must have a setup function def setup(bot): # an extension must have a setup function
bot.add_cog(BotInfo(bot)) # adding a cog bot.add_cog(BotInfo(bot)) # adding a cog

View File

@@ -1,73 +1,73 @@
""" """
lib.Commands lib.Commands
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
Some prepare for commands Some prepare for commands
""" """
from json import load, decoder, dump, JSONDecodeError from json import load, decoder, dump, JSONDecodeError
from os import getenv from os import getenv
from disnake.ext import commands from disnake.ext import commands
async def read_json(guild: int, _param: str): async def read_json(guild: int, _param: str):
""" """
Reads Json file to determite config strings Reads Json file to determite config strings
:param guild: ID of Guild :param guild: ID of Guild
:param _param: Parameter in json file :param _param: Parameter in json file
:return: value of parameter. :return: value of parameter.
""" """
parameter = None parameter = None
with open(getenv('CONF_FILE'), encoding='utf-8') as f: # Open the JSON with open(getenv('CONF_FILE'), encoding='utf-8') as f: # Open the JSON
try: try:
_json = load(f) # Load the custom prefixes _json = load(f) # Load the custom prefixes
except decoder.JSONDecodeError: except decoder.JSONDecodeError:
_json = {} _json = {}
if guild: # If the guild exists if guild: # If the guild exists
try: try:
guild_conf = _json[f"{guild}"] guild_conf = _json[f"{guild}"]
try: try:
parameter = guild_conf[f"{_param}"] parameter = guild_conf[f"{_param}"]
except KeyError: except KeyError:
pass pass
except KeyError: except KeyError:
pass pass
return parameter return parameter
async def write_json(guild: int, param_name: str, param: str or int): async def write_json(guild: int, param_name: str, param: str or int):
with open(getenv('CONF_FILE'), encoding='utf-8') as f: with open(getenv('CONF_FILE'), encoding='utf-8') as f:
try: try:
_json = load(f) _json = load(f)
except decoder.JSONDecodeError: except decoder.JSONDecodeError:
_json = {} _json = {}
try: try:
_guild = _json[f'{guild}'] _guild = _json[f'{guild}']
except KeyError: except KeyError:
_json.update({f'{guild}': {}}) _json.update({f'{guild}': {}})
_guild = _json[f'{guild}'] _guild = _json[f'{guild}']
_guild.update({f'{param_name}': f'{param}'}) _guild.update({f'{param_name}': f'{param}'})
with open(getenv('CONF_FILE'), 'w', encoding='utf-8') as f: with open(getenv('CONF_FILE'), 'w', encoding='utf-8') as f:
dump(_json, f, indent=4) dump(_json, f, indent=4)
def determine_prefix(bot: commands.Bot, msg): def determine_prefix(bot: commands.Bot, msg):
""" """
Determite per-server bot prefix Determite per-server bot prefix
:param bot: Disnake Bot object :param bot: Disnake Bot object
:param msg: Disnake msg object :param msg: Disnake msg object
:return: prefix for server, default is $ :return: prefix for server, default is $
""" """
parameter = '$' parameter = '$'
with open(getenv('CONF_FILE'), encoding='utf-8') as f: # Open the JSON with open(getenv('CONF_FILE'), encoding='utf-8') as f: # Open the JSON
try: try:
_json = load(f) # Load the custom prefixes _json = load(f) # Load the custom prefixes
except JSONDecodeError: except JSONDecodeError:
_json = {} _json = {}
try: try:
parameter = _json[f"{msg.guild.id}"]["prefix"] # Read prefix from json if is setted up parameter = _json[f"{msg.guild.id}"]["prefix"] # Read prefix from json if is setted up
except KeyError: except KeyError:
pass pass
return parameter return parameter

View File

@@ -1,135 +1,135 @@
from sqlite3 import connect, Error from sqlite3 import connect, Error
from lib.Logger import logger from .Logger import logger
class DBReader: class DBReader:
def __init__(self, guildid: int = None): def __init__(self, guildid: int = None):
self._guildid = guildid self._guildid = guildid
self.list = self._read_db(self._guildid) self.list = self._read_db(self._guildid)
self._current_index = 0 self._current_index = 0
def __str__(self) -> str: def __str__(self) -> str:
return str(self._guildid) return str(self._guildid)
@classmethod @classmethod
def _read_db(cls, guildid: int) -> list: def _read_db(cls, guildid: int) -> list:
try: try:
sql_con = connect("user.db") sql_con = connect("user.db")
cursor = sql_con.cursor() cursor = sql_con.cursor()
cursor.execute("""SELECT * FROM "(guildid)" """, cursor.execute("""SELECT * FROM "(guildid)" """,
{'guildid': guildid}) {'guildid': guildid})
record = cursor.fetchall() record = cursor.fetchall()
return record return record
except Error as _e: except Error as _e:
logger.info(f'Error reading DB\n{_e}') logger.info(f'Error reading DB\n{_e}')
def __iter__(self): def __iter__(self):
return _ListGenerationIter(self) return _ListGenerationIter(self)
class _DBAttrs: class _DBAttrs:
def __init__(self, def __init__(self,
userid: int, userid: int,
username: str, username: str,
nick: str, nick: str,
isbot: bool, isbot: bool,
defaulttracks: None or list, defaulttracks: None or list,
usertracks: None or list): usertracks: None or list):
self.userid = userid self.userid = userid
self.username = username self.username = username
self.nick = nick self.nick = nick
self.isbot = isbot self.isbot = isbot
self.defaulttracks = defaulttracks self.defaulttracks = defaulttracks
self.usertracks = usertracks self.usertracks = usertracks
def __str__(self): def __str__(self):
return self.username return self.username
def __repr__(self): def __repr__(self):
return f'<File attrs userid={self.userid} username={self.username} nick={self.nick} ' \ return f'<File attrs userid={self.userid} username={self.username} nick={self.nick} ' \
f'isbot={self.isbot} defaulttracks={self.defaulttracks} usertracks={self.usertracks}>' f'isbot={self.isbot} defaulttracks={self.defaulttracks} usertracks={self.usertracks}>'
class _ListGenerationIter: class _ListGenerationIter:
def __init__(self, user_class): def __init__(self, user_class):
self._current_index = 0 self._current_index = 0
self._list = user_class.list self._list = user_class.list
self._size = len(self._list) self._size = len(self._list)
def __iter__(self): def __iter__(self):
return self return self
def __next__(self): def __next__(self):
if self._current_index < self._size: if self._current_index < self._size:
_userid = self._list[self._current_index][0] _userid = self._list[self._current_index][0]
_username = self._list[self._current_index][1] _username = self._list[self._current_index][1]
_nick = self._list[self._current_index][2] _nick = self._list[self._current_index][2]
_isbot = bool(self._list[self._current_index][3]) _isbot = bool(self._list[self._current_index][3])
_defaulttracks = self._list[self._current_index][4] _defaulttracks = self._list[self._current_index][4]
_usertracks = self._list[self._current_index][5] _usertracks = self._list[self._current_index][5]
self._current_index += 1 self._current_index += 1
memb = _DBAttrs(_userid, memb = _DBAttrs(_userid,
_username, _username,
_nick, _nick,
_isbot, _isbot,
_defaulttracks, _defaulttracks,
_usertracks) _usertracks)
return memb return memb
raise StopIteration raise StopIteration
async def prepare_db(guild: int): async def prepare_db(guild: int):
try: try:
_connect = connect('user.db') _connect = connect('user.db')
cursor = _connect.cursor() cursor = _connect.cursor()
cursor.execute(f'''CREATE TABLE IF NOT EXISTS "{guild}" cursor.execute(f'''CREATE TABLE IF NOT EXISTS "{guild}"
([userid] INTEGER PRIMARY KEY, [username] TEXT, ([userid] INTEGER PRIMARY KEY, [username] TEXT,
[nick] TEXT, [isbot] BOOL, [defaulttracks] TEXT, [usertracks] TEXT)''') [nick] TEXT, [isbot] BOOL, [defaulttracks] TEXT, [usertracks] TEXT)''')
cursor.close() cursor.close()
except Error as _error: except Error as _error:
logger.info(_error) logger.info(_error)
async def work_with_db(db_func: str, data_turple: tuple): async def work_with_db(db_func: str, data_turple: tuple):
""" """
Writing to db per server userinfo Writing to db per server userinfo
:param db_func: :param db_func:
:param data_turple: :param data_turple:
""" """
try: try:
_connect = connect('user.db') _connect = connect('user.db')
cursor = _connect.cursor() cursor = _connect.cursor()
cursor.execute(db_func, data_turple) cursor.execute(db_func, data_turple)
_connect.commit() _connect.commit()
cursor.close() cursor.close()
except Error as _error: except Error as _error:
logger.critical(_error) logger.critical(_error)
async def fill_bd(name: str, userid: int, isbot: bool, nick: str, guild: int): async def fill_bd(name: str, userid: int, isbot: bool, nick: str, guild: int):
sqlite_insert_with_param = (f"""INSERT OR IGNORE INTO "{guild}" sqlite_insert_with_param = (f"""INSERT OR IGNORE INTO "{guild}"
(username, userid, nick, isbot) (username, userid, nick, isbot)
VALUES (?, ?, ?, ?)""") VALUES (?, ?, ?, ?)""")
data_tuple: tuple[str, int, str, bool] = (name, userid, nick, isbot) data_tuple: tuple[str, int, str, bool] = (name, userid, nick, isbot)
await work_with_db(sqlite_insert_with_param, data_tuple) await work_with_db(sqlite_insert_with_param, data_tuple)
async def read_db(guild: int, user: int, column: str): async def read_db(guild: int, user: int, column: str):
_col_dict = {'userid': 0, _col_dict = {'userid': 0,
'username': 1, 'username': 1,
'nick': 2, 'nick': 2,
'isbot': 3, 'isbot': 3,
'defaulttracks': 4, 'defaulttracks': 4,
'usertracks': 5} 'usertracks': 5}
try: try:
sql_con = connect("user.db") sql_con = connect("user.db")
cursor = sql_con.cursor() cursor = sql_con.cursor()
cursor.execute(f"""SELECT * FROM "{guild}" where userid = {user}""") cursor.execute(f"""SELECT * FROM "{guild}" where userid = {user}""")
record = cursor.fetchone() record = cursor.fetchone()
return record[_col_dict[column]] return record[_col_dict[column]]
except Error as _error: except Error as _error:
logger.critical(_error) logger.critical(_error)

View File

@@ -1,86 +1,86 @@
from mimetypes import guess_type from mimetypes import guess_type
from os import walk from os import walk
class ListGenerator: class ListGenerator:
def __init__(self, path: str = None): def __init__(self, path: str = None):
self.path = path self.path = path
self.list: list = self._lister(self.path) self.list: list = self._lister(self.path)
try: try:
self._size = len(self.list) self._size = len(self.list)
except TypeError: except TypeError:
pass pass
self._current_index = 0 self._current_index = 0
def __str__(self) -> str: def __str__(self) -> str:
return 'Audio iter generator' return 'Audio iter generator'
@classmethod @classmethod
def _lister(cls, path) -> list: def _lister(cls, path) -> list:
_list: list = [] _list: list = []
try: try:
for f in walk(path): for f in walk(path):
_list.extend(f) _list.extend(f)
break break
return sorted(_list[2]) return sorted(_list[2])
except TypeError: except TypeError:
pass pass
def __iter__(self): def __iter__(self):
return _ListGenerationIter(self) return _ListGenerationIter(self)
def __next__(self): def __next__(self):
if self._current_index < self._size: if self._current_index < self._size:
self._current_index += 1 self._current_index += 1
class _FileAttrs: class _FileAttrs:
def __init__(self, name, path, mimetype, exc): def __init__(self, name, path, mimetype, exc):
self.name = name self.name = name
self.path = path self.path = path
self.mimetype = mimetype self.mimetype = mimetype
self.exc = exc self.exc = exc
def __str__(self): def __str__(self):
return self.name return self.name
def __repr__(self): def __repr__(self):
return f'<File attrs name={self.name} path={self.path} exc={self.exc} type=<{self.mimetype}> >' return f'<File attrs name={self.name} path={self.path} exc={self.exc} type=<{self.mimetype}> >'
class _ListGenerationIter: class _ListGenerationIter:
def __init__(self, list_class): def __init__(self, list_class):
self._current_index = 0 self._current_index = 0
self._list = list_class.list self._list = list_class.list
self._name = self._list[self._current_index] self._name = self._list[self._current_index]
self._path = list_class.path self._path = list_class.path
self._size = len(self._list) self._size = len(self._list)
def __iter__(self): def __iter__(self):
return self return self
@property @property
def type(self) -> str: def type(self) -> str:
guess = guess_type(f'{self._path}/{self._list[self._current_index]}')[0] guess = guess_type(f'{self._path}/{self._list[self._current_index]}')[0]
return guess return guess
@property @property
def _exc(self) -> str: def _exc(self) -> str:
try: try:
_ret = self._list[self._current_index].split('.')[-1] _ret = self._list[self._current_index].split('.')[-1]
except AttributeError: except AttributeError:
_ret = None _ret = None
return _ret return _ret
def __next__(self): def __next__(self):
if self._current_index < self._size: if self._current_index < self._size:
_name = self._list[self._current_index] _name = self._list[self._current_index]
_path = self._path _path = self._path
_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,52 +1,52 @@
import logging import logging
class _CustomFormatter(logging.Formatter): class _CustomFormatter(logging.Formatter):
grey = "\x1b[38;20m" grey = "\x1b[38;20m"
yellow = "\x1b[33;20m" yellow = "\x1b[33;20m"
red = "\x1b[31;20m" red = "\x1b[31;20m"
bold_red = "\x1b[31;1m" bold_red = "\x1b[31;1m"
reset = "\x1b[0m" reset = "\x1b[0m"
fmt = "%(asctime)s - [%(levelname)s] -%(module)s- %(message)s" fmt = "%(asctime)s - [%(levelname)s] -%(module)s- %(message)s"
FORMATS = { FORMATS = {
logging.DEBUG: grey + fmt + reset, logging.DEBUG: grey + fmt + reset,
logging.INFO: grey + fmt + reset, logging.INFO: grey + fmt + reset,
logging.WARNING: yellow + fmt + reset, logging.WARNING: yellow + fmt + reset,
logging.ERROR: red + fmt + reset, logging.ERROR: red + fmt + reset,
logging.CRITICAL: bold_red + fmt + reset logging.CRITICAL: bold_red + fmt + reset
} }
old_factory = logging.getLogRecordFactory() old_factory = logging.getLogRecordFactory()
def _record_factory(*args, **kwargs): def _record_factory(*args, **kwargs):
record = _CustomFormatter.old_factory(*args, **kwargs) record = _CustomFormatter.old_factory(*args, **kwargs)
_module = record.module _module = record.module
_levelname = record.levelname _levelname = record.levelname
if len(_module) % 2 == 0 and len(_module) < 12: if len(_module) % 2 == 0 and len(_module) < 12:
_module = ' ' * ((12 - len(_module)) // 2) + _module + ' ' * ((12 - len(_module)) // 2) _module = ' ' * ((12 - len(_module)) // 2) + _module + ' ' * ((12 - len(_module)) // 2)
elif len(_module) % 2 == 1 and len(_module) < 12: elif len(_module) % 2 == 1 and len(_module) < 12:
_module = ' ' * ((12 - len(_module)) // 2) + record.module + ' ' * ((12 - len(_module)) // 2 + 1) _module = ' ' * ((12 - len(_module)) // 2) + record.module + ' ' * ((12 - len(_module)) // 2 + 1)
if len(_levelname) % 2 == 0 and len(_levelname) < 8: if len(_levelname) % 2 == 0 and len(_levelname) < 8:
_levelname = ' ' * ((8 - len(_levelname)) // 2) + _levelname + ' ' * ((8 - len(_levelname)) // 2) _levelname = ' ' * ((8 - len(_levelname)) // 2) + _levelname + ' ' * ((8 - len(_levelname)) // 2)
elif len(record.levelname) % 2 == 1 and len(record.module) < 8: elif len(record.levelname) % 2 == 1 and len(record.module) < 8:
_levelname = ' ' * ((8 - len(_levelname)) // 2) + _levelname + ' ' * ((8 - len(_levelname)) // 2 + 1) _levelname = ' ' * ((8 - len(_levelname)) // 2) + _levelname + ' ' * ((8 - len(_levelname)) // 2 + 1)
record.module = _module record.module = _module
record.levelname = _levelname record.levelname = _levelname
return record return record
logging.setLogRecordFactory(_record_factory) logging.setLogRecordFactory(_record_factory)
def format(self, record): def format(self, record):
log_fmt = self.FORMATS.get(record.levelno) log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt, "%d-%m-%Y %H:%M:%S") formatter = logging.Formatter(log_fmt, "%d-%m-%Y %H:%M:%S")
return formatter.format(record) return formatter.format(record)
logger = logging.getLogger('Pisya_Bot') logger = logging.getLogger('Pisya_Bot')
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler() ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG) ch.setLevel(logging.DEBUG)
ch.setFormatter(_CustomFormatter()) ch.setFormatter(_CustomFormatter())
logger.addHandler(ch) logger.addHandler(ch)

View File

@@ -1,17 +1,17 @@
from asyncio import sleep from asyncio import sleep
from disnake import FFmpegOpusAudio from disnake import FFmpegOpusAudio
from .Logger import logger from .Logger import logger
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.error(f'Playing: {audio}') logger.error(f'Playing: {audio}')
vp = await vc.connect() vp = await vc.connect()
if not vp.is_playing(): if not vp.is_playing():
vp.play(FFmpegOpusAudio(f'{audio}', )) vp.play(FFmpegOpusAudio(f'{audio}', ))
while vp.is_playing(): while vp.is_playing():
await sleep(0.5) await sleep(0.5)
await sleep(1) await sleep(1)
await vp.disconnect() await vp.disconnect()

View File

@@ -1,5 +1,5 @@
""" """
lib lib
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
Some libs for the bot which help him Some libs for the bot which help him
""" """

View File

@@ -1,8 +1,13 @@
import os
import sys
import pytest import pytest
from disnake.ext.commands.common_bot_base import CommonBotBase from disnake.ext.commands.common_bot_base import CommonBotBase
from mock import mock from mock import mock
from lib.CogsPrep import cog_list, work_with_cogs sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from bot.lib.CogsPrep import cog_list, work_with_cogs
def test_cog_list(): def test_cog_list():