Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
86ab62b440 | |||
|
3ee02c4411 | ||
f3fbf605d3 | |||
dd9ae4f828 | |||
5084f8d5b3 | |||
a09e81bb6f | |||
8e3113bfca |
6 changed files with 155 additions and 13 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Кэш скопмилированных скриптов
|
||||||
|
__pycache__
|
||||||
|
|
||||||
|
# Сериализованные базы данных
|
||||||
|
*.msgpack
|
0
readme.md
Normal file
0
readme.md
Normal file
|
@ -4,16 +4,21 @@
|
||||||
from os import environ
|
from os import environ
|
||||||
# Получение переменных среды и удаление файлов —
|
# Получение переменных среды и удаление файлов —
|
||||||
# https://docs.python.org/3.12/library/os.html
|
# https://docs.python.org/3.12/library/os.html
|
||||||
|
from database import *
|
||||||
|
# Система управления базой данных —
|
||||||
|
# документация внутри кода
|
||||||
import gitlab, discord
|
import gitlab, discord
|
||||||
# Обертка АПИ ГитЛаба — https://python-gitlab.readthedocs.io/en/latest и
|
# Обертка АПИ ГитЛаба — https://python-gitlab.readthedocs.io/en/latest и
|
||||||
# АПИ Дискорда — https://discordpy.readthedocs.io/en/latest
|
# АПИ Дискорда — https://discordpy.readthedocs.io/en/latest
|
||||||
|
|
||||||
|
|
||||||
|
database = GitlabDiscordDatabase()
|
||||||
database_spisok = dict()
|
database.retrieve # получить данные из сериализованного файла БД
|
||||||
|
|
||||||
|
|
||||||
gitlab_instance = gitlab.Gitlab(url = 'https://gitlab.megu.one', private_token = environ.get("TOKEN_GITLAB")) # определение адреса и токена экземляра ГитЛаба
|
gitlab_instance = gitlab.Gitlab(url = 'https://gitlab.megu.one', private_token = environ.get("TOKEN_GITLAB")) # определение адреса и токена экземляра ГитЛаба
|
||||||
|
'''project = gitlab_instance.projects.get(13)''' # определение проекта в котором нужно создавать задачи
|
||||||
|
# TODO: Привязка экзепмляра и проекта к Дискорд Каналу в БД, а не в коде
|
||||||
|
|
||||||
|
|
||||||
intents = discord.Intents.default() # использовать требования по умолчанию
|
intents = discord.Intents.default() # использовать требования по умолчанию
|
||||||
|
@ -33,30 +38,55 @@ async def on_message(message): # обработка каждого сообще
|
||||||
issue_text = message.content.replace("/issue ","") # получение текста команды «issue»
|
issue_text = message.content.replace("/issue ","") # получение текста команды «issue»
|
||||||
if command('/issue'): # команда создания задачи на ГитЛабе
|
if command('/issue'): # команда создания задачи на ГитЛабе
|
||||||
if database_spisok.get(int(message.channel.id)):
|
if database_spisok.get(int(message.channel.id)):
|
||||||
project = gitlab_instance.projects.get(str(database_spisok.get(int(message.channel.id))))
|
project = gitlab_instance.projects.get(database_spisok.get(int(message.channel.id)))
|
||||||
if project.issues.create({'title': issue_text}):
|
if project.issues.create({'title': issue_text}):
|
||||||
await reply("Задача «`" + issue_text + "`» создана **успешно** ^w^")
|
await reply("Задача «" + issue_text + "» создана успешно, ^w^")
|
||||||
else:
|
else:
|
||||||
await reply("не получилось, QwQ")
|
await reply("не получилось, QwQ")
|
||||||
else:
|
else:
|
||||||
await reply("Данных нет, введите идентификатор проекта через `/project <ID>` ^w^")
|
await reply("данных нет, введите пожалуйста id для подключения через /project (id проекта), ^w^")
|
||||||
|
|
||||||
if command('/project'):
|
'''if command('/project'):
|
||||||
try:
|
try:
|
||||||
database_spisok[int(message.channel.id)] = int(message.content.replace("/project ",""))
|
database_spisok[int(message.channel.id)] = int(message.content.replace("/project ",""))
|
||||||
await reply("Данные сохранены ^w^")
|
open("database.msgpack", "wb").write(msgpack.packb(database_spisok))
|
||||||
|
await reply("данные сохранены ^w^")
|
||||||
except:
|
except:
|
||||||
await reply("Не удалось привязать идентификатор проекта к этому каналу")
|
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:
|
||||||
|
remove("database.msgpack")
|
||||||
|
await reply("данные удалены ^w^")
|
||||||
|
except:
|
||||||
|
await reply("не удалось удалить файлы")
|
||||||
|
|
||||||
if command('/show'):
|
if command('/show'):
|
||||||
if database_spisok.get(int(message.channel.id)):
|
if database.get_project(message.channel.id):
|
||||||
await reply(database_spisok.get(int(message.channel.id)))
|
await reply(database.get_project(message.channel.id))
|
||||||
else:
|
else:
|
||||||
await reply("Данных нет, введите идентификатор проекта через `/project <ID>` ^w^")
|
await reply("данных нет, введите id для подключения через /project (id проекта), ^w^")
|
||||||
|
|
||||||
if command('/speak'):
|
if command('/speak'):
|
||||||
await reply("я бот для создания проектов на gitlab через дискорд созданный Артёмом (ака: TheRandomFurryGuy) и Богданом богом данным (ака: Zaboal) | [идея сделать меня фурри была предложена 1-м ради шутки]")
|
await reply("я бот для создания проектов на gitlab через дискорд созданный Артёмом (ака: TheRandomFurryGuy) и Богданом богом данным (ака: Zaboal) | [идея сделать меня фурри была предложена 1-м ради шутки]")
|
||||||
await reply("====================================")
|
await reply("====================================")
|
||||||
await reply("список комманд которые я выполняю:\n/issue - создание задачи на gitlab\n/project - подключение id канала discord с id канала gitlab\n/remove - удаление id\n/show - показ id (к каждому каналу discord подключён отдельный id gitlab)\n/speak - я расскажу немного о себе (что сейчас и делаю)")
|
await reply("список комманд которые я выполняю:\n/issue - создание задачи на gitlab\n/project - подключение id канала discord с id канала gitlab\n/remove - удаление id\n/show - показ id (к каждому каналу discord подключён отдельный id gitlab)\n/speak - я расскажу немного о себе (что сейчас и делаю)")
|
||||||
|
|
||||||
discord_bot.run(str(environ.get("TOKEN_DISCORD"))) # авторизация бота по токену из среды и запуск
|
'''if command('/save'):
|
||||||
|
open("database.msgpack", "wb").write(msgpack.packb(database_spisok))'''
|
||||||
|
|
||||||
|
discord_bot.run(environ.get("TOKEN_DISCORD")) # авторизация бота по токену из среды и запуск
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Регистрировать команды бота в Команды Приложения —
|
||||||
|
# https://discordpy.readthedocs.io/en/latest/interactions/api.html#application-commands:
|
||||||
|
#=======================================================================
|
84
source/gitlab-discord_bot/database.py
Normal file
84
source/gitlab-discord_bot/database.py
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
''' База данных бота-интегратора Дискорда и ГитЛаба
|
||||||
|
© Стешенко Артём и Зажигин Богдан 2023—2023 '''
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
|
@ -1,2 +1,5 @@
|
||||||
discord.py
|
discord.py
|
||||||
python-gitlab
|
python-gitlab
|
||||||
|
dataclasses
|
||||||
|
msgpack
|
||||||
|
os
|
20
source/gitlab-discord_bot/test_database.py
Normal file
20
source/gitlab-discord_bot/test_database.py
Normal 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()
|
Loading…
Add table
Reference in a new issue