114 Commits
master ... v0.1

Author SHA1 Message Date
bb2966a867 testing registry 2024-05-29 22:04:33 +03:00
5915bde104 testing registry 2024-05-29 22:01:20 +03:00
1ac50de2d1 testing registry 2024-05-29 22:00:32 +03:00
693d865b95 testing registry 2024-05-29 21:58:24 +03:00
fff65ba25d testing registry 2024-05-29 21:55:28 +03:00
40bf30b19f testing registry 2024-05-29 21:51:11 +03:00
3e4f8937f3 testing registry 2024-05-29 21:47:40 +03:00
a9eb223616 testing registry 2024-05-29 21:46:01 +03:00
b515fb0f81 testing registry 2024-05-29 21:43:38 +03:00
9a280d3814 testing registry 2024-05-29 21:37:01 +03:00
031758c2cd added requrement.txt 2024-05-29 21:31:23 +03:00
9fb61e2b98 Merge remote-tracking branch 'origin/test' into test
# Conflicts:
#	.gitlab-ci.yml
2024-05-29 21:22:10 +03:00
aafa3c33a9 added requrement.txt 2024-05-29 21:21:41 +03:00
Slava
01792e12da Update .gitlab-ci.yml file 2024-05-29 18:11:24 +00:00
6801d9a0fd added requrement.txt 2024-05-29 21:05:28 +03:00
f314a50e3f Merge remote-tracking branch 'origin/test' into test 2024-05-29 20:51:18 +03:00
c22b71353f added requrement.txt 2024-05-29 20:50:54 +03:00
Slava
899527436f Update .gitlab-ci.yml file 2024-05-29 17:12:12 +00:00
Slava
95ac0caf30 Update .gitlab-ci.yml file 2024-05-29 12:23:28 +00:00
Slava
27f4cd6122 Update file .gitlab-ci.yml 2024-05-29 12:22:27 +00:00
39ec9b9bf7 added requrement.txt 2024-05-29 04:54:17 +03:00
1aaa489f55 added requrement.txt 2024-05-29 04:04:46 +03:00
bb3fda4778 added requrement.txt 2024-05-29 03:45:44 +03:00
c108d7d32c added requrement.txt 2024-05-29 02:31:18 +03:00
9bb86699f7 added requrement.txt 2024-05-29 02:27:24 +03:00
c9f6407149 added requrement.txt 2024-05-29 02:21:32 +03:00
335c661a34 added requrement.txt 2024-05-29 02:20:24 +03:00
bc304827f5 added requrement.txt 2024-05-29 02:19:48 +03:00
9a143ba84a added requrement.txt 2024-05-29 02:15:55 +03:00
Slava
9fc0c4c071 Update .gitlab-ci.yml file 2024-05-28 22:39:09 +00:00
Slava
1852f4ebe2 Update .gitlab-ci.yml file 2024-05-28 21:41:28 +00:00
bacon
37eef98e20 docker bush ended 2024-03-22 01:07:29 +03:00
bacon
62a8921e10 docker bush ended 2024-03-21 21:04:00 +03:00
bacon
14dd773d5c docker 2024-03-21 18:37:56 +03:00
bacon
c8d2f7c344 docker 2024-03-21 18:35:23 +03:00
bacon
720cff55c1 docker 2024-03-21 18:27:49 +03:00
Slava
4a539becca Update Dockerfile 2024-03-21 09:13:34 +00:00
bacon
734427d16f docker 2024-03-21 10:59:41 +03:00
bacon
fa08480a34 docker 2024-03-21 10:32:53 +03:00
bacon
581d9d4c84 docker 2024-03-21 02:47:04 +03:00
bacon
bbb597f5f6 docker 2024-03-21 02:42:40 +03:00
bacon
109f61c146 Merge remote-tracking branch 'gitlab/test' into test 2024-03-21 02:26:28 +03:00
bacon
f9ce4c9d2d docker 2024-03-21 02:26:22 +03:00
Slava
2725b7a499 Удалить .editorconfig 2024-03-20 23:15:59 +00:00
bacon
721b33d963 docker 2024-03-21 01:59:53 +03:00
bacon
b3e8502804 docker 2024-03-21 01:59:13 +03:00
bacon
9652cac405 docker 2024-03-21 01:53:17 +03:00
bacon
cd182db4ba docker 2024-03-21 01:52:20 +03:00
bacon
fde794e7aa docker 2024-03-21 01:44:58 +03:00
bacon
efb5fd0531 docker 2024-03-21 01:39:39 +03:00
bacon
641ab7c3fb docker 2024-03-21 00:27:30 +03:00
bacon
0e7a32f36a docker 2024-03-21 00:21:45 +03:00
bacon
7faad7df23 docker 2024-03-20 23:58:32 +03:00
bacon
43457b7fc1 docker 2024-03-20 23:58:06 +03:00
bacon
5ee3403c3f docker 2024-03-20 23:51:20 +03:00
bacon
5f8cf83d35 docker 2024-03-20 23:40:58 +03:00
bacon
e3cdb3812a docker 2024-03-20 23:39:26 +03:00
bacon
50ccbca4be docker 2024-03-20 23:38:44 +03:00
bacon
f19bcabe61 docker 2024-03-20 23:19:41 +03:00
Slava
f33ec2fc20 Update .gitlab-ci.yml file 2024-03-20 20:16:34 +00:00
bacon
877348711e docker 2024-03-20 22:57:52 +03:00
bacon
52c1d2717e docker 2024-03-20 22:40:13 +03:00
bacon
7adfe234fb docker 2024-03-20 22:31:21 +03:00
Slava
e867dd23c1 Update .gitlab-ci.yml file 2024-03-20 19:24:02 +00:00
bacon
99ded107f1 Merge remote-tracking branch 'gitlab/test' into test 2024-03-20 22:21:26 +03:00
bacon
fc492d1ba8 docker 2024-03-20 22:21:09 +03:00
Slava
f98c77faf9 Update .gitlab-ci.yml file 2024-03-17 23:33:46 +00:00
bacon
da9755e948 Merge remote-tracking branch 'gitlab/test' into test 2024-03-18 02:27:15 +03:00
bacon
98e71f66e9 fixed start after move 2024-03-18 02:27:01 +03:00
Slava
ca1837318d Update .gitlab-ci.yml file 2024-03-17 23:12:28 +00:00
bacon
76d1625346 fixed start after move 2024-03-18 02:08:16 +03:00
bacon
fff1a5c0c7 fixed start after move 2024-03-18 01:49:40 +03:00
bacon
e1fc05dea2 Merge remote-tracking branch 'gitlab/test' into test 2024-03-18 01:05:05 +03:00
bacon
d352541a86 fixed start after move 2024-03-18 01:04:53 +03:00
Slava
1a6c0c1f49 Update .gitlab-ci.yml file 2024-03-17 21:51:47 +00:00
bacon
361a39420a fixed start after move 2024-03-18 00:44:04 +03:00
bacon
765acd0d42 fixed start after move 2024-03-18 00:43:18 +03:00
bacon
ee277e44c8 Merge remote-tracking branch 'gitlab/test' into test
# Conflicts:
#	.gitlab-ci.yml
2024-03-18 00:39:59 +03:00
bacon
eaaffd2056 fixed start after move 2024-03-18 00:38:57 +03:00
Slava
4598294bd1 Update .gitlab-ci.yml file 2024-03-17 21:33:40 +00:00
bacon
4c5a5718fc fixed start after move 2024-03-18 00:24:27 +03:00
bacon
29246e7b97 fixed start after move 2024-03-18 00:19:14 +03:00
bacon
3048bf1f51 test coverage 2024-03-17 23:01:59 +03:00
bacon
d93654043a changes in test 2024-03-17 22:56:37 +03:00
Slava
93198bf82b Update .gitlab-ci.yml file 2024-03-17 19:20:26 +00:00
Slava
e60793315b Update .gitlab-ci.yml file 2024-03-17 19:18:21 +00:00
bacon
d1e62a3941 changes in test 2024-03-17 22:13:07 +03:00
bacon
758d775a5b Update .gitlab-ci.yml file 2024-03-17 22:07:39 +03:00
bacon
d22c3ca6b6 updated structure 2024-03-17 22:03:27 +03:00
bacon
4e535f6580 updated lib_Cog test 2024-03-17 21:34:03 +03:00
bacon
cb72e48f09 Merge remote-tracking branch 'gitlab/test' into test
# Conflicts:
#	tests/test_lib_Cog.py
2024-03-17 17:15:42 +03:00
bacon
786c580b47 uptated requrements.txt 2024-03-17 17:14:13 +03:00
Slava
46de864da3 Update test_lib_Cog.py 2024-03-17 12:45:36 +00:00
Slava
a4e672597c Update CogsPrep.py 2024-03-17 12:30:23 +00:00
Slava
9fa7624be7 Update test_lib_Cog.py 2024-03-17 11:59:10 +00:00
Slava
073be5e629 Update .gitlab-ci.yml file 2024-03-17 11:56:02 +00:00
Slava
16ea4ede05 Update .gitlab-ci.yml file 2024-03-17 11:54:47 +00:00
Slava
b6539a31fc Update .gitlab-ci.yml 2024-03-17 11:50:25 +00:00
Slava
6a07ef45f2 Update CogsPrep.py 2024-03-17 11:48:47 +00:00
Slava
814f88756c Update test_lib_Cog.py 2024-03-17 11:48:25 +00:00
Slava
49122706a7 Update requirements.txt 2024-03-17 07:01:16 +00:00
Slava
39da2d53fc Update .gitlab-ci.yml file 2024-03-17 07:00:02 +00:00
Slava
7d32b69809 Update requirements.txt 2024-03-17 06:58:51 +00:00
Slava
8fba876e93 Update .gitlab-ci.yml 2024-03-17 06:58:08 +00:00
Slava
a28cd1e421 Update .gitlab-ci.yml file 2024-03-17 06:54:18 +00:00
Slava
ca25888325 Update .gitlab-ci.yml file 2024-03-17 06:46:18 +00:00
Slava
2ec3efbdeb Update .gitlab-ci.yml file 2024-03-17 06:39:39 +00:00
Slava
e31039eb8b Update .gitlab-ci.yml file 2024-03-17 06:38:12 +00:00
Slava
6fe0df2fb7 Update .gitlab-ci.yml 2024-03-17 06:35:51 +00:00
bacon
308272803d uptated requrements.txt 2024-03-17 09:31:49 +03:00
Slava
a9d50dc478 Update .gitlab-ci.yml file 2024-03-17 06:31:20 +00:00
Slava
958c70ef4d Update .gitlab-ci.yml 2024-03-17 06:28:01 +00:00
bacon
fca483e4e6 ended test_lib_Cog.py 2024-03-17 02:17:07 +03:00
bacon
736621c516 added base tests 2024-03-15 15:46:45 +03:00
54 changed files with 1250 additions and 1054 deletions

11
.dockerignore Normal file
View File

@@ -0,0 +1,11 @@
/tmp/
audio/*/
/.idea
user.db
*.pyc
/.run/
.env
*.exe
/venv/
config.json
.editorconfig

11
.gitignore vendored
View File

@@ -1,12 +1,11 @@
/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/ .editorconfig
config.json

View File

@@ -1,67 +1,111 @@
# You can override the included template(s) by including variable overrides
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
# Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages: stages:
- 'test' - 'test'
- 'code_quality' - 'build'
- 'deploy' - 'push'
sast: pytest:
stage: 'test' stage: 'test'
include: image: python
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/SAST-IaC.gitlab-ci.yml
qodana:
stage: 'code_quality'
needs: ['gemnasium-python-dependency_scanning', 'semgrep-sast', 'kics-iac-sast']
only: only:
- master - test
- merge_requests - tags
image:
name: jetbrains/qodana-python-community
entrypoint:
- ''
cache: cache:
- key: qodana-2023.3-$CI_DEFAULT_BRANCH-$CI_COMMIT_REF_SLUG
fallback_keys:
- qodana-2023.3-$CI_DEFAULT_BRANCH-
- qodana-2023.3-
paths: paths:
- ".qodana/cache" - $CI_PROJECT_DIR/venv/
variables:
QODANA_TOKEN: "$qodana_token"
script:
- qodana --save-report --results-dir=$CI_PROJECT_DIR/.qodana/results --cache-dir=$CI_PROJECT_DIR/.qodana/cache
artifacts:
expose_as: qodana_report
expire_in: 1 week
paths:
- ".qodana/results/"
push:
stage: 'deploy'
image: 'alpine'
needs: ['qodana']
only:
- master
before_script: before_script:
- apk add openssh-client > /dev/null - cd $CI_PROJECT_DIR
- eval $(ssh-agent -s) - python -m venv venv
- chmod 400 $SSH_PRIVATE_KEY - chmod u+x venv/bin/activate
- source venv/bin/activate
- mkdir -p ~/.ssh - pip install --upgrade --quiet pip
- chmod 700 ~/.ssh - pip install --quiet -U -r requirements.txt
- pip install --quiet -U -r tests/requirements.txt
- cp $SSH_PRIVATE_KEY ~/.ssh/id_rsa
- ssh-add ~/.ssh/id_rsa
script: script:
- ssh $BOT_HOST -oStrictHostKeyChecking=accept-new 'cd /opt/discord/tarkov && git pull' - pytest -v
variables:
# DOCKER_HOST: tcp://docker:2375
# fill those if you have a proxy in your environment
DOCKER_DRIVER: overlay2
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: "/certs"
make_image:
stage: build
needs:
- pytest
image: docker:26.1.3
services:
- docker:26.1.3-dind
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
# fetches the latest image (not failing if image is not found)
- docker pull $CI_REGISTRY_IMAGE:latest || true
# builds the project, passing proxy variables, using OCI labels
# notice the cache-from, which is going to use the image we just pulled locally
# the built image is tagged locally with the commit SHA, and then pushed to
# the GitLab registry
- >
DOCKER_BUILDKIT=1 docker build
--pull
--cache-from $CI_REGISTRY_IMAGE:latest
--label "org.opencontainers.image.title=$CI_PROJECT_TITLE"
--label "org.opencontainers.image.url=$CI_PROJECT_URL"
--label "org.opencontainers.image.created=$CI_JOB_STARTED_AT"
--label "org.opencontainers.image.revision=$CI_COMMIT_SHA"
--label "org.opencontainers.image.version=$CI_COMMIT_REF_NAME"
--tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
.
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
# Here, the goal is to tag the "master" branch as "latest"
Push latest:
variables:
# We are just playing with Docker here.
# We do not need GitLab to clone the source code.
GIT_STRATEGY: none
stage: push
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
# Because we have no guarantee that this job will be picked up by the same runner
# that built the image in the previous step, we pull it again locally
- docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
# Then we tag it "latest"
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:latest
# Annnd we push it.
- docker push $CI_REGISTRY_IMAGE:latest
# Finally, the goal here is to Docker tag any Git tag
# GitLab will start a new pipeline everytime a Git tag is created, which is pretty awesome
Push commit:
variables:
# Again, we do not need the source code here. Just playing with Docker.
GIT_STRATEGY: none
stage: push
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
Push tag:
variables:
# Again, we do not need the source code here. Just playing with Docker.
GIT_STRATEGY: none
stage: push
only:
# We want this job to be run on tags only.
- tags
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG

View File

@@ -1,2 +0,0 @@
0.0.5
Initial

22
Dockerfile Normal file
View File

@@ -0,0 +1,22 @@
FROM python:3.12.2-slim-bookworm as builder
LABEL authors="bacon"
WORKDIR /app
COPY requirements.txt /app
RUN pip wheel install \
--no-cache-dir -q \
--no-deps --wheel-dir /app/wheels \
-r requirements.txt
FROM python:3.12.2-slim-bookworm as runner
WORKDIR /app
COPY --from=builder /app/wheels /wheels
RUN apt-get update -qq && \
apt-get install -qq --no-install-recommends ffmpeg -y && \
apt-get clean -qq autoclean && \
pip install --no-cache -q /wheels/*
COPY src/ /app
ENTRYPOINT ["python", "bot.py"]
#ENTRYPOINT ["ffmpeg"]

0
docker-compose.yml Normal file
View File

View File

@@ -1,45 +0,0 @@
"""
lib.CogsPrepare
~~~~~~~~~~~~~
Loads, unloads Cogs files
cog_list: return list of cog filenames
work_with_cogs: loads, reloads and unloads cogs files
"""
from os import listdir, rename
from typing import List
from disnake.ext import commands
from .Logger import logger
async def cog_list(fold: str = './cogs') -> List[str]:
cogs_list = []
for _filename in listdir(fold):
if _filename.endswith('.py'):
cogs_list.append(_filename[:-3])
return cogs_list
async def work_with_cogs(what_do, bot: commands.Bot, cog):
if isinstance(cog, str):
cog = cog.split()
for _filename in cog:
if what_do == "load":
bot.load_extension(f'cogs.{_filename}')
logger.info(f'Loaded cog {_filename}')
elif what_do == 'unload':
bot.unload_extension(f'cogs.{_filename}')
logger.info(f'Cog {_filename} unloaded')
elif what_do == 'reload':
bot.reload_extension(f'cogs.{_filename}')
logger.info(f'Cog {_filename} reloaded')
elif what_do == 'disable':
bot.unload_extension(f'cogs.{_filename}')
rename(f'cogs/{_filename}.py', f'cogs/disabled/{_filename}.py')
logger.info(f'Cog {_filename} stopped and disabled')
elif what_do == 'enable':
rename(f'cogs/disabled/{_filename}.py', f'cogs/{_filename}.py')
bot.load_extension(f'cogs.{_filename}')
logger.info(f'Cog {_filename} started and enabled')

View File

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

View File

@@ -1,6 +0,0 @@
version: "1.0"
bootstrap: |
rm -rf .idea
pip install -U -r requirements.txt
profile:
name: qodana.recommended

Binary file not shown.

View File

@@ -1,16 +1,16 @@
__version__ = '0.0.7' __version__ = '0.0.7'
__title__ = "Pisya_bot" __title__ = "src"
__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)

319
bot.py → src/bot.py Executable file → Normal file
View File

@@ -1,161 +1,158 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
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 integral_lib.CogsPrep import work_with_cogs, cog_list
from __init__ import __version__ as ver from integral_lib.Comands import determine_prefix
from lib.CogsPrep import work_with_cogs, cog_list from integral_lib.Logger import logger
from lib.Comands import determine_prefix
from lib.Logger import logger load_dotenv()
if not isfile('.env') or not getenv('CONF_FILE'):
load_dotenv() with open('.env', 'a', encoding='utf-8') as f:
if not isfile('.env') or not getenv('CONF_FILE'): f.write("CONF_FILE='config.json'\n")
with open('.env', 'a', encoding='utf-8') as f: load_dotenv()
f.write("CONF_FILE='config.json'\n") if not isfile(getenv('CONF_FILE')):
load_dotenv() with open(getenv('CONF_FILE'), 'a', encoding='utf-8') as f:
if not isfile(getenv('CONF_FILE')): f.write("")
with open(getenv('CONF_FILE'), 'a', encoding='utf-8') as f:
f.write("") intents = Intents(messages=True,
guilds=True,
intents = Intents(messages=True, message_content=True,
guilds=True, voice_states=True,
message_content=True, members=True,
voice_states=True, presences=True
members=True, )
presences=True
) bot = Bot(command_prefix=determine_prefix,
intents=intents,
bot = Bot(command_prefix=determine_prefix, reload=True,
intents=intents, test_guilds=[648126669122568215]
reload=True, )
test_guilds=[648126669122568215]
) bot.i18n.load("locale/")
bot.i18n.load("locale/") work_with_cogs('load', bot, cog_list())
asyncio.run(work_with_cogs('load', bot, asyncio.run(cog_list())))
@bot.event
async def on_ready():
@bot.event logger.info('Bot started')
async def on_ready(): logger.info(f'Disnake version {__version__}')
logger.info('Bot started') logger.info(f'We have logged in as {bot.user}')
logger.info(f'Disnake version {__version__}')
logger.info(f'We have logged in as {bot.user}')
logger.info(f'Version of bot is - v{ver}') @bot.slash_command(
name='cog',
options=[
@bot.slash_command( Option(
name='cog', name=Localized('cog', key="COG".lower()),
options=[ description=Localized("cog file", key="COG_FILE"),
Option( type=OptionType.string
name=Localized('cog', key="COG".lower()), )
description=Localized("cog file", key="COG_FILE"), ]
type=OptionType.string )
) @is_owner()
] async def slash_cogs(inter: ApplicationCommandInteraction):
) """
@is_owner() Working with cogs (modules) {{SLASH_COG}}
async def slash_cogs(inter: ApplicationCommandInteraction):
""" Parameters
Working with cogs (modules) {{SLASH_COG}} ----------
:param inter:
Parameters """
---------- pass
:param inter:
"""
pass @slash_cogs.sub_command(description=Localized("Enables Cog", key="ENABLE_COG"))
async def enable(inter: ApplicationCommandInteraction, cog: str):
"""
@slash_cogs.sub_command(description=Localized("Enables Cog", key="ENABLE_COG"))
async def enable(inter: ApplicationCommandInteraction, cog: str): Parameters
""" ----------
:param inter:
Parameters :param cog: Select Cogfile {{COG_FILE}}
---------- """
:param inter: await work_with_cogs('enable', bot, cog)
:param cog: Select Cogfile {{COG_FILE}} await inter.response.send_message(f'Cog {cog} is enabled', ephemeral=True)
"""
await work_with_cogs('enable', bot, cog)
await inter.response.send_message(f'Cog {cog} is enabled', ephemeral=True) @slash_cogs.sub_command(description=Localized("Disables Cog", key="DISABLE_COG"))
async def disable(inter: ApplicationCommandInteraction, cog: str):
"""
@slash_cogs.sub_command(description=Localized("Disables Cog", key="DISABLE_COG"))
async def disable(inter: ApplicationCommandInteraction, cog: str): Parameters
""" ----------
:param inter:
Parameters :param cog: Select Cogfile {{COG_FILE}}
---------- """
:param inter: await work_with_cogs('disable', bot, cog)
:param cog: Select Cogfile {{COG_FILE}} await inter.response.send_message(f'Cog {cog} is disabled', ephemeral=True)
"""
await work_with_cogs('disable', bot, cog)
await inter.response.send_message(f'Cog {cog} is disabled', ephemeral=True) @slash_cogs.sub_command(description=Localized("Loads Cog", key="LOAD_COG"))
async def load(inter: ApplicationCommandInteraction, cog: str):
"""
@slash_cogs.sub_command(description=Localized("Loads Cog", key="LOAD_COG"))
async def load(inter: ApplicationCommandInteraction, cog: str): Parameters
""" ----------
:param inter:
Parameters :param cog: Select Cogfile {{COG_FILE}}
---------- """
:param inter: await work_with_cogs('load', bot, cog)
:param cog: Select Cogfile {{COG_FILE}} await inter.response.send_message(f'Cog {cog} is loaded', ephemeral=True)
"""
await work_with_cogs('load', bot, cog)
await inter.response.send_message(f'Cog {cog} is loaded', ephemeral=True) @slash_cogs.sub_command(description=Localized("Unload Cog", key="UNLOAD_COG"))
async def unload(inter: ApplicationCommandInteraction, cog: str):
"""
@slash_cogs.sub_command(description=Localized("Unload Cog", key="UNLOAD_COG"))
async def unload(inter: ApplicationCommandInteraction, cog: str): Parameters
""" ----------
:param inter:
Parameters :param cog: Select Cogfile {{COG_FILE}}
---------- """
:param inter: await work_with_cogs('unload', bot, cog)
:param cog: Select Cogfile {{COG_FILE}} await inter.response.send_message(f'Cog {cog} is unload', ephemeral=True)
"""
await work_with_cogs('unload', bot, cog)
await inter.response.send_message(f'Cog {cog} is unload', ephemeral=True) @slash_cogs.sub_command(description=Localized("Reloads Cog", key="RELOAD_COG"))
async def reload(inter: ApplicationCommandInteraction, cog: str):
"""
@slash_cogs.sub_command(description=Localized("Reloads Cog", key="RELOAD_COG"))
async def reload(inter: ApplicationCommandInteraction, cog: str): Parameters
""" ----------
:param inter:
Parameters :param cog: Select Cogfile {{COG_FILE}}
---------- """
:param inter: await work_with_cogs('reload', bot, cog)
:param cog: Select Cogfile {{COG_FILE}} await inter.response.send_message(f'Cog {cog} is reloaded', ephemeral=True)
"""
await work_with_cogs('reload', bot, cog)
await inter.response.send_message(f'Cog {cog} is reloaded', ephemeral=True) @disable.autocomplete('cog')
@unload.autocomplete('cog')
@load.autocomplete('cog')
@disable.autocomplete('cog') @reload.autocomplete('cog')
@unload.autocomplete('cog') async def _cog_opt(inter: ApplicationCommandInteraction, current: str):
@load.autocomplete('cog') current = current.lower()
@reload.autocomplete('cog') _list = cog_list(fold='./cogs/')
async def _cog_opt(inter: ApplicationCommandInteraction, current: str): return [choice for choice in _list if current in choice.lower()]
current = current.lower()
_list = await cog_list(fold='./cogs/')
return [choice for choice in _list if current in choice.lower()] @enable.autocomplete('cog')
async def _cog_opt(inter: ApplicationCommandInteraction, current: str):
current = current.lower()
@enable.autocomplete('cog') _list = cog_list(fold='./cogs/disabled/')
async def _cog_opt(inter: ApplicationCommandInteraction, current: str): return [choice for choice in _list if current in choice.lower()]
current = current.lower()
_list = await cog_list(fold='./cogs/disabled/')
return [choice for choice in _list if current in choice.lower()] @slash_cogs.error
async def cogs_error(inter: ApplicationCommandInteraction):
await inter.response.send_message(Localized("Error", key="EROR"), ephemeral=True)
@slash_cogs.error logger.error(f'User {inter.author} tries to use cogs func')
async def cogs_error(inter: ApplicationCommandInteraction):
await inter.response.send_message(Localized("Error", key="EROR"), ephemeral=True)
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 tasks
from lib.Comands import read_json, write_json from integral_lib.Comands import *
from lib.DB_Worker import fill_bd, prepare_db, work_with_db from integral_lib.DB_Worker import fill_bd, prepare_db, work_with_db
from lib.Logger import logger from integral_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 src 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 src 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 src 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 src 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 src 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 src", 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 src 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 src 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,84 @@
import random import random
import disnake import disnake
from disnake import OptionChoice, Option, OptionType, Member, VoiceState from disnake import OptionChoice, Option, OptionType, Member, VoiceState, ApplicationCommandInteraction
from disnake.ext import commands from disnake.ext import commands
from lib.Logger import logger from integral_lib.ListGenerator import ListGenerator
from lib.Player import play_audio from integral_lib.Logger import logger
from lib.ListGenerator import ListGenerator from integral_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 integral_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: ApplicationCommandInteraction, current: str):
current = current.lower() """
_dict: dict = {} Asynchronously generates a list of OptionChoices for the given audio files based on the user input.
for f in ListGenerator('audio'): Parameters:
_dict[f.name] = f'{f.path}/{f.name}' - inter: disnake.ApplicationCommandInteraction - The interaction context for the command.
return [ - current: str - The current user input to filter the audio file choices.
OptionChoice(name=choice, value=f'{_dict[choice]}') Returns:
for choice in _dict if current in choice.lower() - list[OptionChoice] - A list of OptionChoice objects representing the available audio file choices.
] :param current:
:param inter: ApplicationCommandInteraction
"""
def setup(bot): # an extension must have a setup function current = current.lower()
bot.add_cog(Audio(bot)) # adding a cog _dict: dict = {}
for f in ListGenerator('audio'):
_dict[f.name] = f'{f.path}/{f.name}'
return [
OptionChoice(name=choice, value=f'{_dict[choice]}')
for choice in _dict if current in choice.lower()
]
def setup(bot): # an extension must have a setup function
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 integral_lib.Comands import write_json
from lib.Logger import logger from integral_lib.Logger import logger
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 src 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 src",
) )
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 integral_lib import YandexPlayer
from lib.Logger import logger from integral_lib.Logger 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 src 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 integral_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 src 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,42 +1,44 @@
import os import os
import disnake
import psutil import disnake
import psutil
from disnake.ext import commands from disnake import ApplicationCommandInteraction
from __init__ import version_info as ver from disnake.ext import commands
from lib.Comands import determine_prefix
from lib.Logger import logger from __init__ import version_info as ver
from integral_lib.Comands import determine_prefix
from integral_lib.Logger import logger
class BotInfo(commands.Cog, name='Bot Info'):
def __init__(self, bot: commands.Bot):
self.bot = bot # defining bot as global var in class class BotInfo(commands.Cog, name='Bot Info'):
def __init__(self, bot: commands.Bot):
@commands.Cog.listener() # this is a decorator for events/listeners self.bot = bot # defining src as global var in class
async def on_ready(self):
logger.info(f'Cog {__name__.split(".")[1]} is ready!.') @commands.Cog.listener() # this is a decorator for events/listeners
async def on_ready(self):
@commands.slash_command(name="info_bot", logger.info(f'Cog {__name__.split(".")[1]} is ready!.')
description='Shows general info about bot') # this is for making a command
async def info_bot(self, inter: disnake.ApplicationCommandInteraction): @commands.slash_command(name="info_bot",
_pid = os.getpid() description='Shows general info about src') # this is for making a command
_process = psutil.Process(_pid) async def info_bot(self, inter: ApplicationCommandInteraction):
emb = disnake.Embed( _pid = os.getpid()
title="General information", _process = psutil.Process(_pid)
description="General information on about bot", emb = disnake.Embed(
) title="General information",
emb.set_thumbnail(self.bot.user.avatar.url) description="General information on about src",
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" emb.set_thumbnail(self.bot.user.avatar.url)
f'Bot ping: {round(self.bot.latency * 1000)}\n' emb.add_field(name="System info:", value=f"Memory Usage: {round(_process.memory_info().rss / 2 ** 20, 2)} Mb\n"
f'Prefix: `{determine_prefix(self.bot, inter)}\n`' f"CPU Usage: {_process.cpu_percent()}%\n"
) f'Bot ping: {round(self.bot.latency * 1000)}\n'
emb.add_field(name="Bot info:", value="Bot owner: <@386629192743256065>\n" f'Prefix: `{determine_prefix(self.bot, inter)}\n`'
f"Bot version: {ver.major}.{ver.minor}.{ver.micro}-{ver.releaselevel}") )
emb.set_footer(text=f"Information requested by: {inter.author.display_name}") emb.add_field(name="Bot info:", value="Bot owner: <@386629192743256065>\n"
f"Bot version: {ver.major}.{ver.minor}.{ver.micro}-{ver.releaselevel}")
await inter.response.send_message(embed=emb, ephemeral=True) emb.set_footer(text=f"Information requested by: {inter.author.display_name}")
await inter.response.send_message(embed=emb, ephemeral=True)
def setup(bot): # an extension must have a setup function
bot.add_cog(BotInfo(bot)) # adding a cog
def setup(bot): # an extension must have a setup function
bot.add_cog(BotInfo(bot)) # adding a cog

View File

@@ -0,0 +1,78 @@
"""
integral_lib.CogsPrepare
~~~~~~~~~~~~~
Loads, unloads Cogs files
cog_list: return list of cog filenames
work_with_cogs: loads, reloads and unloads cogs files
"""
from os import listdir, rename
from typing import List
from disnake.ext.commands.interaction_bot_base import InteractionBotBase
from .Logger import logger
def cog_list(fold: str = './cogs') -> List[str]:
"""
A function that generates a list of cog names based on the files present in a specified folder.
Parameters:
- fold (str): The directory path where the cog files are located. Defaults to './cogs'.
Returns:
- List[str]: A list of cog names without the '.py' extension.
"""
cogs_list = []
for _filename in listdir(fold):
if _filename.endswith('.py'):
cogs_list.append(_filename[:-3])
return cogs_list
def work_with_cogs(what_do: str,
bot: InteractionBotBase,
cog: str | list):
"""
Perform the specified action on the given cog or list of cogs.
Args:
what_do (str): The action to perform (load, unload, reload, disable, enable).
src (InteractionBotBase): The src instance to work with.
cog (str | list): The name of the cog or a list of cogs to work with.
Raises:
ValueError: If the action is not recognized.
Returns:
None
--------
:param cog: str | list
:param bot: InteractionBotBase
:param what_do: str = ['load', 'unload', 'reload', 'disable', 'enable']
"""
if isinstance(cog, str):
cog = cog.split()
for _filename in cog:
if _filename.endswith('.py'):
_filename = _filename.split('.')[0]
if what_do == "load":
bot.load_extension(f'cogs.{_filename}')
logger.info(f'Cog {_filename} loaded')
elif what_do == 'unload':
bot.unload_extension(f'cogs.{_filename}')
logger.info(f'Cog {_filename} unloaded')
elif what_do == 'reload':
bot.reload_extension(f'cogs.{_filename}')
logger.info(f'Cog {_filename} reloaded')
elif what_do == 'disable':
bot.unload_extension(f'cogs.{_filename}')
rename(f'cogs/{_filename}.py',
f'cogs/disabled/{_filename}.py')
logger.info(f'Cog {_filename} stopped and disabled')
elif what_do == 'enable':
rename(f'cogs/disabled/{_filename}.py',
f'cogs/{_filename}.py')
bot.load_extension(f'cogs.{_filename}')
logger.info(f'Cog {_filename} started and enabled')
else:
raise ValueError(f"Unrecognized action: {what_do}")

View File

@@ -1,71 +1,86 @@
""" """
lib.Commands integral_lib.Commands
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
Some prepare for commands Some prepare for commands
"""
from json import load, decoder, dump, JSONDecodeError
from os import getenv """
from json import load, decoder, dump, JSONDecodeError
from disnake.ext import commands from os import getenv
from disnake.ext import commands
async def read_json(guild: int, _param: str):
"""
Reads Json file to determite config strings async def read_json(guild: int, _param: str):
:param guild: ID of Guild """
:param _param: Parameter in json file Reads Json file to determite config strings
:return: value of parameter. :param guild: ID of Guild
""" :param _param: Parameter in json file
parameter = None :return: value of parameter.
with open(getenv('CONF_FILE'), encoding='utf-8') as f: # Open the JSON """
try: parameter = None
_json = load(f) # Load the custom prefixes with open(getenv('CONF_FILE'), encoding='utf-8') as f: # Open the JSON
except decoder.JSONDecodeError: try:
_json = {} _json = load(f) # Load the custom prefixes
if guild: # If the guild exists except decoder.JSONDecodeError:
try: _json = {}
guild_conf = _json[f"{guild}"] if guild: # If the guild exists
try: try:
parameter = guild_conf[f"{_param}"] guild_conf = _json[f"{guild}"]
except KeyError: try:
pass parameter = guild_conf[f"{_param}"]
except KeyError: except KeyError:
pass pass
return parameter except KeyError:
pass
return parameter
async def write_json(guild: int, param_name: str, param: str or int):
with open(getenv('CONF_FILE'), encoding='utf-8') as f:
try: async def write_json(guild: int, param_name: str, param: str or int):
_json = load(f) """
except decoder.JSONDecodeError: A function to write JSON data to a file after updating or adding a parameter value.
_json = {}
try: Parameters:
_guild = _json[f'{guild}']
except KeyError: - guild: an integer representing the guild ID
_json.update({f'{guild}': {}}) - param_name: a string representing the parameter name
_guild = _json[f'{guild}'] - param: a string or integer representing the parameter value
_guild.update({f'{param_name}': f'{param}'})
with open(getenv('CONF_FILE'), 'w', encoding='utf-8') as f: Returns:
dump(_json, f, indent=4) This function does not return anything.
"""
with open(getenv('CONF_FILE'), encoding='utf-8') as f:
def determine_prefix(bot: commands.Bot, msg): try:
""" _json = load(f)
Determite per-server bot prefix except decoder.JSONDecodeError:
:param bot: Disnake Bot object _json = {}
:param msg: Disnake msg object try:
:return: prefix for server, default is $ _guild = _json[f'{guild}']
""" except KeyError:
parameter = '$' _json.update({f'{guild}': {}})
with open(getenv('CONF_FILE'), encoding='utf-8') as f: # Open the JSON _guild = _json[f'{guild}']
try: _guild.update({f'{param_name}': f'{param}'})
_json = load(f) # Load the custom prefixes with open(getenv('CONF_FILE'), 'w', encoding='utf-8') as f:
except JSONDecodeError: dump(_json, f, indent=4)
_json = {}
try:
parameter = _json[f"{msg.guild.id}"]["prefix"] # Read prefix from json if is setted up def determine_prefix(bot: commands.Bot, msg):
"""
except KeyError: Determine the per-server src prefix based on the given message object.
pass
return parameter :param bot: Disnake Bot object
:param msg: Disnake msg object
:return: prefix for server, default is $
"""
parameter = '$'
with open(getenv('CONF_FILE'), encoding='utf-8') as f: # Open the JSON
try:
_json = load(f) # Load the custom prefixes
except JSONDecodeError:
_json = {}
try:
parameter = _json[f"{msg.guild.id}"]["prefix"] # Read prefix from json if is setted up
except KeyError:
pass
return parameter

View File

@@ -1,135 +1,134 @@
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(f"""SELECT * FROM "{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}"\n'
cursor.execute(f'''CREATE TABLE IF NOT EXISTS "{guild}" f' ([userid] INTEGER PRIMARY KEY, [username] TEXT,\n'
([userid] INTEGER PRIMARY KEY, [username] TEXT, f' [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 FFmpegPCMAudio
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(FFmpegPCMAudio(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

@@ -0,0 +1,5 @@
"""
integral_lib
~~~~~~~~~~~~~
Some libs for the src which help him
"""

BIN
tests/requirements.txt Normal file

Binary file not shown.

41
tests/test_bot.py Normal file
View File

@@ -0,0 +1,41 @@
from disnake import Intents
from disnake.ext import commands
intents = Intents(messages=True,
message_content=True,
)
class Cog(commands.Cog):
@commands.command()
async def my_cmd(self, ctx):
pass
class CogTwo(commands.Cog):
async def bot_check(self, ctx) -> bool:
pass
class CogThree(commands.Cog):
async def bot_check_once(self, ctx) -> bool:
pass
class CogFour(commands.Cog):
async def bot_slash_command_check(self, ctx) -> bool:
pass
class CogFive(commands.Cog):
async def can_run(self, ctx) -> bool:
pass
def test_bot():
bot = commands.Bot(command_prefix='$', intents=intents)
bot.add_cog(Cog())
bot.add_cog(CogTwo())
bot.add_cog(CogThree())
bot.add_cog(CogFour())
bot.add_cog(CogFive())

31
tests/test_lib_Cog.py Normal file
View File

@@ -0,0 +1,31 @@
import sys
import pytest
from disnake.ext.commands.common_bot_base import CommonBotBase
from mock import mock
sys.path.append('src')
from integral_lib import CogsPrep
def test_cog_list():
with mock.patch('integral_lib.CogsPrep.listdir') as MockClass:
MockClass.return_value = ['cog1.py', 'cog2.py']
result = CogsPrep.cog_list()
assert result == ['cog1', 'cog2']
@pytest.mark.parametrize("cog", ["cog1.py", "cog2"])
@pytest.mark.parametrize("what_do", ['load', 'unload', 'reload', 'disable', 'enable'])
def test_work_with_cogs(what_do, cog):
with mock.patch('integral_lib.CogsPrep.rename') as mock_rename:
mock_rename.return_value = None
mock_bot = mock.MagicMock(spec=CommonBotBase)
result = CogsPrep.work_with_cogs(what_do, mock_bot, cog)
if what_do in ['load', 'enable']:
assert mock_bot.load_extension.called
elif what_do in ['unload', 'disable']:
assert mock_bot.unload_extension.called
elif what_do == 'reload':
assert mock_bot.reload_extension.called