Compare commits

...
Sign in to create a new pull request.

7 commits
master ... dev

6 changed files with 133 additions and 45 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
# Кэш скопмилированных скриптов
__pycache__
# Сериализованные базы данных
*.msgpack

0
readme.md Normal file
View file

View file

@ -1,24 +1,19 @@
''' Интеграция Дискорда и ГитЛаба
© Стешенко Артём и Зажигин Богдан 20232023 '''
from os import environ, remove
from os import environ
# Получение переменных среды и удаление файлов —
# https://docs.python.org/3.12/library/os.html
import msgpack
# Бинарная сериализация, создание машинной базы данных —
# https://github.com/msgpack/msgpack-python/blob/main/README.md
from database import *
# Система управления базой данных —
# документация внутри кода
import gitlab, discord
# Обертка АПИ ГитЛаба — https://python-gitlab.readthedocs.io/en/latest и
# АПИ Дискорда — https://discordpy.readthedocs.io/en/latest
try:
with open("database.msgpack", "rb") as database:
database_content = database.read()
database_spisok = msgpack.unpackb(database_content, strict_map_key=False)
except:
database_spisok = dict()
database = GitlabDiscordDatabase()
database.retrieve # получить данные из сериализованного файла БД
gitlab_instance = gitlab.Gitlab(url = 'https://gitlab.megu.one', private_token = environ.get("TOKEN_GITLAB")) # определение адреса и токена экземляра ГитЛаба
@ -51,13 +46,22 @@ async def on_message(message): # обработка каждого сообще
else:
await reply("данных нет, введите пожалуйста id для подключения через /project (id проекта), ^w^")
if command('/project'):
'''if command('/project'):
try:
database_spisok[int(message.channel.id)] = int(message.content.replace("/project ",""))
open("database.msgpack", "wb").write(msgpack.packb(database_spisok))
await reply("данные сохранены ^w^")
except:
await reply("не удалось сохранить id")
await reply("не удалось сохранить ссылку на проект")'''
if command('/setup'):
try:
content = message.content.replace("/setup ","").split(" ")
setup = GitlabDiscordBinding(content[0], content[1], int(message.channel.id), int(message.author.id))
database.update(setup)
await reply(database)
except:
await reply("asdadadfa")
if command('/remove'): # команда удаления базы данных
try:
@ -67,8 +71,8 @@ async def on_message(message): # обработка каждого сообще
await reply("не удалось удалить файлы")
if command('/show'):
if database_spisok.get(int(message.channel.id)):
await reply(database_spisok.get(int(message.channel.id)))
if database.get_project(message.channel.id):
await reply(database.get_project(message.channel.id))
else:
await reply("данных нет, введите id для подключения через /project (id проекта), ^w^")
@ -85,32 +89,4 @@ discord_bot.run(environ.get("TOKEN_DISCORD")) # авторизация бота
# TODO: Регистрировать команды бота в Команды Приложения —
# https://discordpy.readthedocs.io/en/latest/interactions/api.html#application-commands:
#=======================================================================
'''tree_commands = discord.app_commands.CommandTree(discord_bot) # Объявление дерева команд бота
if message.content.startswith('/project'):
slovar.update({message.channel.id: message.content.replace("/project ","")})
await reply(slovar)
slovar = dict()
command_issue_extras = dict()
@tree_commands.command(name="issue", description="создать задачу на GitLab", nsfw=False, auto_locale_strings=False)
async def issue(interaction):
await interaction.response.send_message(f"Pong", ephemeral=True)
add_command(*command_issue, guild=None, guilds=None, override=True)
asyncio.run(sync(*command_issue, guild=None))'''
#=======================================================================
'''database_file = open("database.msgpack", "w")
database = msgpack.unpackb(database_file.read()) # \31123\123123\123132\213
# {1: a}, {2: b}
Ctrl+c = SINGal TERMinate
database[3] = "c"
# {1: a}, {2: b}, {3, c}
# /save
database_file.write(
msgpack.packb(database, use_bin_type=True) # \31123\123123\123132\213 + \123123123123
)
database_file.close()'''
#=======================================================================

View file

@ -0,0 +1,84 @@
''' База данных бота-интегратора Дискорда и ГитЛаба
© Стешенко Артём и Зажигин Богдан 20232023 '''
from dataclasses import dataclass, field, astuple
# Описание структур данных —
# https://docs.python.org/3/library/dataclasses.html
from msgpack import packb, unpackb
# Бинарная сериализация, создание машинной базы данных —
# https://github.com/msgpack/msgpack-python/blob/main/README.md
from yarl import URL
@dataclass
class GitlabDiscordBinding:
"""Данные, необходимые для интеграции Дискорд Канала и Гитлаб Проекта."""
discord_user_gitlab_token: str # Персональный токен Дискорд Пользователя для ГитЛаба
gitlab_project_url: str # URL ГитЛаб Проекта для которого подходит токен
discord_channel_id: int # Идентификационный номер Дискорд Канала для работы с проектом в ГитЛабе
discord_user_id: int # Идентификационный номер Дискорд Пользователя
# def get_project_id(self):
def get_project_host_url(self):
project_host_url = "https://" + str(URL(self.gitlab_project_url).host)
return project_host_url
@dataclass
class GitlabDiscordDatabase:
""" Методы для работы со списком значений «`GitlabDiscordBinding`». """
gitlab_discord_bindings: list[GitlabDiscordBinding] = field(default_factory = lambda: [GitlabDiscordBinding("0", "0", 0, 0)])
filename: str = "gitlab-discord.msgpack"
def save(self, filename: str = filename) -> None:
""" Подготовка базы данных и сохранение её сериализации
файл с названием «`gitlab-discord.msgpack`» по умолчанию. """
file = open(filename, "wb")
serialization = packb(astuple(self))
file.write(serialization) # type: ignore
def retrieve(self, filename: str = filename) -> bool:
""" Установление значений из сериализованного файла
базы данных в с названием «gitlab-discord.msgpack» по умолчанию. """
def prepare(basic_list: list) -> list[GitlabDiscordBinding]:
database = list()
for element in range(len(basic_list)):
database.append(GitlabDiscordBinding(
discord_user_gitlab_token = basic_list[element][0],
gitlab_project_url = basic_list[element][1],
discord_channel_id = basic_list[element][2],
discord_user_id = basic_list[element][3]
))
return database
try:
file = open(filename, "rb")
content = file.read()
basic_list = unpackb(content)
self.gitlab_discord_bindings = prepare(basic_list)
return True
except:
return False
def get_project(self, discord_channel_id: int):
for binding in range(len(self.gitlab_discord_bindings)):
if self.gitlab_discord_bindings[binding].discord_channel_id == discord_channel_id:
return self.gitlab_discord_bindings[binding].gitlab_project_url
def update(self, current_binding: GitlabDiscordBinding):
for binding in range(len(self.gitlab_discord_bindings)):
if self.gitlab_discord_bindings[binding].discord_channel_id == current_binding.discord_channel_id and self.gitlab_discord_bindings[binding].discord_user_id == current_binding.discord_user_id:
self.gitlab_discord_bindings[binding] = current_binding
elif self.gitlab_discord_bindings[binding].gitlab_project_url != current_binding.gitlab_project_url and self.gitlab_discord_bindings[binding].discord_user_gitlab_token != current_binding.discord_user_gitlab_token:
self.gitlab_discord_bindings.append(current_binding)

View file

@ -1,2 +1,5 @@
discord.py
python-gitlab
python-gitlab
dataclasses
msgpack
os

View file

@ -0,0 +1,20 @@
from database import GitlabDiscordBinding, GitlabDiscordDatabase
case1 = GitlabDiscordBinding(
"glpat-dZ-QokqKdaXVKdFwgi2j",
"https://gitlab.megu.one/zaboal_org/gitlab-discord_bot",
1089910716926021782,
1024406341726515332)
print(case1)
case2 = GitlabDiscordBinding(
"sadfjpisuadfhmnccxv",
"https://gitlab.megu.one/zaboal_org/s[odfsaldkhsdf",
213482740912374,
2384912087409213847)
print(case2)
database = GitlabDiscordDatabase([case1, case2])
print(database)
database.save()