37 changed files with 2607 additions and 2655 deletions
@ -0,0 +1,37 @@ |
|||||||
|
# -*- coding: utf8 -*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
# Права пользователей |
||||||
|
|
||||||
|
from bot_sys import bot_bd |
||||||
|
|
||||||
|
# --------------------------------------------------------- |
||||||
|
# БД |
||||||
|
table_name = 'module_access' |
||||||
|
mod_name_field = 'modName' |
||||||
|
moduleaccess_field = 'modAccess' |
||||||
|
mod_default_access_field = 'itemDefaultAccess' |
||||||
|
|
||||||
|
access_denied_message = ''' |
||||||
|
❌ Доступ запрещён! |
||||||
|
''' |
||||||
|
|
||||||
|
def GetAccessForModuleRequest(module_name, access, default_access): |
||||||
|
return f"INSERT OR IGNORE INTO {table_name} ({mod_name_field}, {moduleaccess_field}, {mod_default_access_field}) VALUES ('{module_name}', '{access}', '{default_access}');" |
||||||
|
|
||||||
|
def GetModulesAccessList(a_Bot): |
||||||
|
return bot_bd.RequestSelectTemplate(a_Bot, table_name)() |
||||||
|
|
||||||
|
def GetAccessForModule(a_Bot, a_ModuleName): |
||||||
|
alist = GetModulesAccessList(a_Bot) |
||||||
|
for i in alist: |
||||||
|
if i[0] == a_ModuleName: |
||||||
|
return i[1] |
||||||
|
return '' |
||||||
|
|
||||||
|
def GetItemDefaultAccessForModule(a_Bot, a_ModuleName): |
||||||
|
alist = GetModulesAccessList(a_Bot) |
||||||
|
for i in alist: |
||||||
|
if i[0] == a_ModuleName: |
||||||
|
return i[2] |
||||||
|
return '' |
@ -0,0 +1,200 @@ |
|||||||
|
# -*- coding: utf8 -*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
# Сообщения |
||||||
|
|
||||||
|
from bot_sys import bot_bd, keyboard, user_access, bd_table, bot_messages |
||||||
|
from bot_modules import mod_table_operate, mod_simple_message, access_utils |
||||||
|
from template import bd_item |
||||||
|
|
||||||
|
from aiogram.dispatcher import FSMContext |
||||||
|
from aiogram.dispatcher.filters.state import State, StatesGroup |
||||||
|
|
||||||
|
class FSMCreateButton(StatesGroup): |
||||||
|
name = State() |
||||||
|
desc = State() |
||||||
|
photo = State() |
||||||
|
|
||||||
|
class FSMEditButtonPhotoItem(StatesGroup): |
||||||
|
item_id = State() |
||||||
|
item_field = State() |
||||||
|
|
||||||
|
class FSMEditButtonNameItem(StatesGroup): |
||||||
|
item_id = State() |
||||||
|
item_field = State() |
||||||
|
|
||||||
|
class FSMEditButtonDescItem(StatesGroup): |
||||||
|
item_id = State() |
||||||
|
item_field = State() |
||||||
|
|
||||||
|
class FSMEditButtonAccessItem(StatesGroup): |
||||||
|
item_id = State() |
||||||
|
item_field = State() |
||||||
|
# --------------------------------------------------------- |
||||||
|
# БД |
||||||
|
module_name = 'buttons' |
||||||
|
|
||||||
|
table_name = module_name |
||||||
|
key_name = 'buttonID' |
||||||
|
name_field = 'buttonName' |
||||||
|
desc_field = 'buttonDesc' |
||||||
|
photo_field = 'buttonPhoto' |
||||||
|
access_field = 'buttonAccess' |
||||||
|
create_datetime_field = 'buttonCreateDateTime' |
||||||
|
parent_id_field = 'languageID' |
||||||
|
|
||||||
|
table_name_field = bd_table.TableField(name_field, bd_table.TableFieldDestiny.NAME, bd_table.TableFieldType.STR) |
||||||
|
table_parent_id_field = bd_table.TableField(parent_id_field, bd_table.TableFieldDestiny.PARENT_ID, bd_table.TableFieldType.INT) |
||||||
|
|
||||||
|
table = bd_table.Table(table_name, [ |
||||||
|
bd_table.TableField(key_name, bd_table.TableFieldDestiny.KEY, bd_table.TableFieldType.INT), |
||||||
|
table_name_field, |
||||||
|
bd_table.TableField(desc_field, bd_table.TableFieldDestiny.DESC, bd_table.TableFieldType.STR), |
||||||
|
bd_table.TableField(photo_field, bd_table.TableFieldDestiny.PHOTO, bd_table.TableFieldType.STR), |
||||||
|
bd_table.TableField(access_field, bd_table.TableFieldDestiny.ACCESS, bd_table.TableFieldType.STR), |
||||||
|
bd_table.TableField(create_datetime_field, bd_table.TableFieldDestiny.CREATE_DATE, bd_table.TableFieldType.STR), |
||||||
|
table_parent_id_field, |
||||||
|
], |
||||||
|
[ |
||||||
|
[table_name_field, table_parent_id_field], |
||||||
|
] |
||||||
|
) |
||||||
|
|
||||||
|
init_access = f'{user_access.user_access_group_all}=-' |
||||||
|
|
||||||
|
fsm = { |
||||||
|
mod_table_operate.FSMs.CREATE: FSMCreateButton, |
||||||
|
mod_table_operate.FSMs.EDIT_NAME: FSMEditButtonNameItem, |
||||||
|
mod_table_operate.FSMs.EDIT_DESC: FSMEditButtonDescItem, |
||||||
|
mod_table_operate.FSMs.EDIT_PHOTO: FSMEditButtonPhotoItem, |
||||||
|
mod_table_operate.FSMs.EDIT_ACCESS: FSMEditButtonAccessItem, |
||||||
|
} |
||||||
|
|
||||||
|
# --------------------------------------------------------- |
||||||
|
# Сообщения и кнопки |
||||||
|
|
||||||
|
button_names = { |
||||||
|
mod_simple_message.ButtonNames.START: "❍ Названия кнопок", |
||||||
|
mod_table_operate.ButtonNames.LIST: "📃 Список названий кнопок", |
||||||
|
mod_table_operate.ButtonNames.ADD: "☑ Добавить название кнопки", |
||||||
|
mod_table_operate.ButtonNames.EDIT: "🛠 Редактировать названия кнопок", |
||||||
|
mod_table_operate.ButtonNames.EDIT_PHOTO: "☐ Изменить изображение у названия кнопок", |
||||||
|
mod_table_operate.ButtonNames.EDIT_NAME: "≂ Изменить название у названия кнопок", |
||||||
|
mod_table_operate.ButtonNames.EDIT_DESC: "𝌴 Изменить описание у названия кнопок", |
||||||
|
mod_table_operate.ButtonNames.EDIT_ACCESS: "✋ Изменить доступ к названию кнопки", |
||||||
|
mod_table_operate.ButtonNames.DEL: "❌ Удалить название кнопки", |
||||||
|
} |
||||||
|
|
||||||
|
messages = { |
||||||
|
mod_simple_message.Messages.START: f''' |
||||||
|
<b>{button_names[mod_simple_message.ButtonNames.START]}</b> |
||||||
|
|
||||||
|
''', |
||||||
|
mod_table_operate.Messages.SELECT: ''' |
||||||
|
Пожалуйста, выберите название кнопки: |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.ERROR_FIND: ''' |
||||||
|
❌ Ошибка, название кнопки не найдено |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.OPEN: f''' |
||||||
|
<b>Название кнопки: #{name_field}</b> |
||||||
|
|
||||||
|
#{desc_field} |
||||||
|
|
||||||
|
Время создания: #{create_datetime_field} |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.CREATE_NAME: ''' |
||||||
|
Создание названия кнопки Шаг №1 |
||||||
|
|
||||||
|
Введите название название кнопки: |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.CREATE_DESC: ''' |
||||||
|
Создание названия кнопки. Шаг №2 |
||||||
|
|
||||||
|
Введите описание название кнопки: |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.CREATE_PHOTO: ''' |
||||||
|
Создание названия кнопки |
||||||
|
Загрузите обложку для названия кнопок (Фото): |
||||||
|
На данный момент не поддерживается! |
||||||
|
Нажмите пропустить |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Название кнопки успешно добавлено!''', |
||||||
|
mod_table_operate.Messages.START_EDIT: ''' |
||||||
|
Пожалуйста, выберите действие: |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.SELECT_TO_EDIT: ''' |
||||||
|
Выберите название кнопки, который вы хотите отредактировать. |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.EDIT_PHOTO: ''' |
||||||
|
Загрузите новую обложку для названия кнопок (Фото): |
||||||
|
Она будет отображаться в его описании. |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.EDIT_NAME: f''' |
||||||
|
Текущее название названия кнопок: |
||||||
|
#{name_field} |
||||||
|
|
||||||
|
Введите новое название названия кнопки: |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.EDIT_DESC: f''' |
||||||
|
Текущее описание названия кнопок: |
||||||
|
#{desc_field} |
||||||
|
|
||||||
|
Введите новое описание названия кнопки: |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.EDIT_ACCESS: f''' |
||||||
|
Текущий доступ к названию кнопки: |
||||||
|
#{access_field} |
||||||
|
|
||||||
|
{user_access.user_access_readme} |
||||||
|
|
||||||
|
Введите новую строку доступа: |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.SUCCESS_EDIT: '''✅ Название кнопки успешно отредактировано!''', |
||||||
|
mod_table_operate.Messages.SELECT_TO_DELETE: ''' |
||||||
|
Выберите название кнопки, которое вы хотите удалить. |
||||||
|
''', |
||||||
|
mod_table_operate.Messages.SUCCESS_DELETE: '''✅ Название кнопки успешно удалено!''', |
||||||
|
} |
||||||
|
|
||||||
|
class ModuleButtons(mod_table_operate.TableOperateModule): |
||||||
|
def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log): |
||||||
|
super().__init__(table, messages, button_names, fsm, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log) |
||||||
|
|
||||||
|
def GetName(self): |
||||||
|
return module_name |
||||||
|
|
||||||
|
def AddOrIgnoreMessage(self, a_Message): |
||||||
|
table_name = self.m_Table.GetName() |
||||||
|
name_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.NAME) |
||||||
|
photo_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PHOTO) |
||||||
|
desc_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.DESC) |
||||||
|
access_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.ACCESS) |
||||||
|
create_datetime_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.CREATE_DATE) |
||||||
|
parent_id_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PARENT_ID) |
||||||
|
|
||||||
|
lang_id = self.GetModule(self.m_ParentModName).GetLangID(a_Message.m_Language) |
||||||
|
return self.m_Bot.SQLRequest(f'INSERT OR IGNORE INTO {table_name}({photo_field}, {name_field}, {desc_field}, {access_field}, {parent_id_field}, {create_datetime_field}) VALUES(?, ?, ?, ?, ?, {bot_bd.GetBDDateTimeNow()})', |
||||||
|
commit = True, return_error = True, param = (a_Message.m_PhotoID, a_Message.m_MessageName, a_Message.m_MessageDesc, access_utils.GetItemDefaultAccessForModule(self.m_Bot, module_name), lang_id)) |
||||||
|
|
||||||
|
def FlushMessages(self): |
||||||
|
msg = self.m_BotButtons.GetMessages() |
||||||
|
for lang, msg_dict in msg.items(): |
||||||
|
for msg_name, message in msg_dict.items(): |
||||||
|
self.AddOrIgnoreMessage(message) |
||||||
|
|
||||||
|
table_name = self.m_Table.GetName() |
||||||
|
msgs_bd = bd_item.GetAllItemsTemplate(self.m_Bot, table_name)() |
||||||
|
if msgs_bd: |
||||||
|
for m in msgs_bd: |
||||||
|
name = m[1] |
||||||
|
desc = m[2] |
||||||
|
photo_id = m[3] |
||||||
|
lang_id = m[6] |
||||||
|
lang_name = self.GetModule(self.m_ParentModName).GetLangName(lang_id) |
||||||
|
self.m_BotButtons.CreateMessage(name, desc, self.m_Log.GetTimeNow(), a_MessagePhotoID = photo_id, a_MessageLang = lang_name) |
||||||
|
|
||||||
|
self.m_BotButtons.UpdateSignal(self.m_Log.GetTimeNow()) |
||||||
|
|
||||||
|
def OnChange(self): |
||||||
|
self.FlushMessages() |
@ -0,0 +1,16 @@ |
|||||||
|
# -*- coding: utf8 -*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
# Группы пользователей |
||||||
|
|
||||||
|
from bot_sys import user_access |
||||||
|
|
||||||
|
def GetUserGroupData(a_Bot, a_UserID): |
||||||
|
def GetGroupNamesForUser(a_UserID): |
||||||
|
return a_Bot.SQLRequest('SELECT groupName FROM user_groups WHERE group_id=(SELECT group_id FROM user_in_groups WHERE user_id = ?)', param = [a_UserID]) |
||||||
|
r = GetGroupNamesForUser(a_UserID) |
||||||
|
groups = [] |
||||||
|
for i in r: |
||||||
|
if len(i) > 0: |
||||||
|
groups += [i[0]] |
||||||
|
return user_access.UserGroups(a_UserID, groups) |
@ -0,0 +1,15 @@ |
|||||||
|
# -*- coding: utf8 -*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
class ModuleAgregator: |
||||||
|
def __init__(self): |
||||||
|
self.m_Modules = {} |
||||||
|
|
||||||
|
def GetModule(self, a_ModName): |
||||||
|
return self.m_Modules[a_ModName] |
||||||
|
|
||||||
|
def AddModule(self, a_Module): |
||||||
|
self.m_Modules[a_Module.GetName()] = a_Module |
||||||
|
|
||||||
|
def GetModList(self): |
||||||
|
return self.m_Modules.values() |
@ -0,0 +1,25 @@ |
|||||||
|
# -*- coding: utf8 -*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
from abc import ABC, abstractmethod |
||||||
|
|
||||||
|
class IModule(ABC): |
||||||
|
@abstractmethod |
||||||
|
def GetName(self): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def GetInitBDCommands(self): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def GetAccess(self): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def GetModuleButtons(self): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def RegisterHandlers(self): |
||||||
|
pass |
@ -0,0 +1,112 @@ |
|||||||
|
# -*- coding: utf8 -*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
# Простой модуль с одним сообщением |
||||||
|
|
||||||
|
from bot_sys import keyboard, user_access |
||||||
|
from bot_modules import access_utils, mod_interface |
||||||
|
from template import simple_message, bd_item |
||||||
|
|
||||||
|
from enum import Enum |
||||||
|
from enum import auto |
||||||
|
|
||||||
|
class ButtonNames(Enum): |
||||||
|
START = auto() |
||||||
|
|
||||||
|
class Messages(Enum): |
||||||
|
START = auto() |
||||||
|
|
||||||
|
class SimpleMessageModule(mod_interface.IModule): |
||||||
|
def __init__(self, a_Messages, a_Buttons, a_InitAccess, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log): |
||||||
|
self.m_ChildModuleNameList = a_ChildModuleNameList |
||||||
|
self.m_InitAccess = a_InitAccess |
||||||
|
self.m_Bot = a_Bot |
||||||
|
self.m_ModuleAgregator = a_ModuleAgregator |
||||||
|
self.m_BotMessages = a_BotMessages |
||||||
|
self.m_BotButtons = a_BotButtons |
||||||
|
self.m_Log = a_Log |
||||||
|
|
||||||
|
self.m_Buttons = {} |
||||||
|
for name, button_name in a_Buttons.items(): |
||||||
|
self.m_Buttons[name] = self.CreateButton(name, button_name) |
||||||
|
|
||||||
|
self.m_Messages = {} |
||||||
|
for name, message in a_Messages.items(): |
||||||
|
self.m_Messages[name] = self.CreateMessage(name, message) |
||||||
|
|
||||||
|
async def StartMessageHandler(a_Message, state = None): |
||||||
|
return await self.StartMessageHandler(a_Message, state) |
||||||
|
self.m_StartMessageHandlerFunc = StartMessageHandler |
||||||
|
|
||||||
|
def GetAccess(): |
||||||
|
return self.GetAccess() |
||||||
|
self.m_GetAccessFunc = GetAccess |
||||||
|
|
||||||
|
def GetStartKeyboardButtons(a_Message, a_UserGroups): |
||||||
|
return self.GetStartKeyboardButtons(a_Message, a_UserGroups) |
||||||
|
self.m_GetStartKeyboardButtonsFunc = GetStartKeyboardButtons |
||||||
|
|
||||||
|
self.m_StartMessageHandler = simple_message.SimpleMessageTemplate( |
||||||
|
self.m_Bot, |
||||||
|
self.m_StartMessageHandlerFunc, |
||||||
|
self.m_GetStartKeyboardButtonsFunc, |
||||||
|
None, |
||||||
|
self.m_GetAccessFunc |
||||||
|
) |
||||||
|
|
||||||
|
# Основной обработчик главного сообщения |
||||||
|
async def StartMessageHandler(self, a_Message, state = None): |
||||||
|
return simple_message.WorkFuncResult(self.GetMessage(Messages.START)) |
||||||
|
|
||||||
|
def GetButton(self, a_ButtonName): |
||||||
|
return self.m_Buttons.get(a_ButtonName, None) |
||||||
|
|
||||||
|
def GetMessage(self, a_MessageNames): |
||||||
|
return self.m_Messages.get(a_MessageNames, None) |
||||||
|
|
||||||
|
def CreateMessage(self, a_MessageName, a_MessageDesc): |
||||||
|
msg = self.m_BotMessages.CreateMessage(f'{self.GetName()} {a_MessageName}', a_MessageDesc, self.m_Log.GetTimeNow()) |
||||||
|
return msg |
||||||
|
|
||||||
|
def CreateButton(self, a_ButtonName, a_ButtonDesc): |
||||||
|
assert len(a_ButtonDesc) < 41 # Телеграм не поддерживает больше |
||||||
|
assert a_ButtonDesc[0] != ' ' # Телеграм не поддерживает пробелы в начале |
||||||
|
assert a_ButtonDesc[-1:] != ' ' # Телеграм не поддерживает пробелы в конце |
||||||
|
btn = self.m_BotButtons.CreateMessage(f'{self.GetName()} {a_ButtonName}', a_ButtonDesc, self.m_Log.GetTimeNow()) |
||||||
|
return btn |
||||||
|
|
||||||
|
def GetModule(self, a_ModName): |
||||||
|
return self.m_ModuleAgregator.GetModule(a_ModName) |
||||||
|
|
||||||
|
def GetButtons(self, a_ModNameList): |
||||||
|
buttons = [] |
||||||
|
for n in a_ModNameList: |
||||||
|
m = self.m_ModuleAgregator.GetModule(n) |
||||||
|
b = m.GetModuleButtons() |
||||||
|
if not b is None or len(b) != 0: |
||||||
|
buttons += b |
||||||
|
return buttons |
||||||
|
|
||||||
|
def GetStartKeyboardButtons(self, a_Message, a_UserGroups): |
||||||
|
buttons = self.GetButtons(self.m_ChildModuleNameList) |
||||||
|
return keyboard.MakeButtons(self.m_Bot, buttons, a_UserGroups) |
||||||
|
|
||||||
|
def GetInitBDCommands(self): |
||||||
|
return [ |
||||||
|
access_utils.GetAccessForModuleRequest(self.GetName(), self.m_InitAccess, self.m_InitAccess), |
||||||
|
] |
||||||
|
|
||||||
|
def GetAccess(self): |
||||||
|
return access_utils.GetAccessForModule(self.m_Bot, self.GetName()) |
||||||
|
|
||||||
|
def GetModuleButtons(self): |
||||||
|
return [ |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.START), user_access.AccessMode.VIEW, self.GetAccess()), |
||||||
|
] |
||||||
|
|
||||||
|
def RegisterHandlers(self): |
||||||
|
self.m_Bot.RegisterMessageHandler( |
||||||
|
self.m_StartMessageHandler, |
||||||
|
bd_item.GetCheckForTextFunc(self.GetButton(ButtonNames.START)) |
||||||
|
) |
||||||
|
|
@ -0,0 +1,386 @@ |
|||||||
|
# -*- coding: utf8 -*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
# Модуль для редактирования и просмотра таблицы в БД |
||||||
|
|
||||||
|
from bot_sys import keyboard, user_access, bd_table, bot_bd |
||||||
|
from bot_modules import access_utils, mod_simple_message |
||||||
|
from template import simple_message, bd_item, bd_item_select, bd_item_view, bd_item_delete, bd_item_add, bd_item_edit |
||||||
|
|
||||||
|
from enum import Enum |
||||||
|
from enum import auto |
||||||
|
|
||||||
|
class ButtonNames(Enum): |
||||||
|
LIST = auto() |
||||||
|
ADD = auto() |
||||||
|
EDIT = auto() |
||||||
|
EDIT_PHOTO = auto() |
||||||
|
EDIT_NAME = auto() |
||||||
|
EDIT_DESC = auto() |
||||||
|
EDIT_ACCESS = auto() |
||||||
|
EDIT_DEFAULT_ACCESS = auto() |
||||||
|
DEL = auto() |
||||||
|
|
||||||
|
class Messages(Enum): |
||||||
|
SELECT = auto() |
||||||
|
ERROR_FIND = auto() |
||||||
|
OPEN = auto() |
||||||
|
CREATE_NAME = auto() |
||||||
|
CREATE_DESC = auto() |
||||||
|
CREATE_PHOTO = auto() |
||||||
|
SUCCESS_CREATE = auto() |
||||||
|
START_EDIT = auto() |
||||||
|
SELECT_TO_EDIT = auto() |
||||||
|
EDIT_PHOTO = auto() |
||||||
|
EDIT_NAME = auto() |
||||||
|
EDIT_DESC = auto() |
||||||
|
EDIT_ACCESS = auto() |
||||||
|
EDIT_DEFAULT_ACCESS = auto() |
||||||
|
SUCCESS_EDIT = auto() |
||||||
|
SELECT_TO_DELETE = auto() |
||||||
|
SUCCESS_DELETE = auto() |
||||||
|
|
||||||
|
class FSMs(Enum): |
||||||
|
CREATE = auto() |
||||||
|
EDIT_PHOTO = auto() |
||||||
|
EDIT_NAME = auto() |
||||||
|
EDIT_DESC = auto() |
||||||
|
EDIT_ACCESS = auto() |
||||||
|
EDIT_DEFAULT_ACCESS = auto() |
||||||
|
|
||||||
|
class TableOperateModule(mod_simple_message.SimpleMessageModule): |
||||||
|
def __init__(self, a_Table, a_Messages, a_Buttons, a_FSMs, a_ParentModName, a_ChildModName, a_InitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log): |
||||||
|
super().__init__(a_Messages, a_Buttons, a_InitAccess, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log) |
||||||
|
self.m_Table = a_Table |
||||||
|
self.m_FSMs = a_FSMs |
||||||
|
self.m_EditModuleNameList = a_EditModuleNameList |
||||||
|
self.m_ChildModName = a_ChildModName |
||||||
|
self.m_ParentModName = a_ParentModName |
||||||
|
self.m_SelectPrefix = '' |
||||||
|
|
||||||
|
def GetEditKeyboardButtons(a_Message, a_UserGroups): |
||||||
|
return self.GetEditKeyboardButtons(a_Message, a_UserGroups) |
||||||
|
self.m_GetEditKeyboardButtonsFunc = GetEditKeyboardButtons |
||||||
|
|
||||||
|
def GetButtonNameAndKeyValueAndAccess(a_Item): |
||||||
|
return self.GetButtonNameAndKeyValueAndAccess(a_Item) |
||||||
|
self.m_GetButtonNameAndKeyValueAndAccessFunc = GetButtonNameAndKeyValueAndAccess |
||||||
|
|
||||||
|
async def PreDelete(a_CallbackQuery, a_Item): |
||||||
|
return await self.PreDelete(a_CallbackQuery, a_Item) |
||||||
|
self.m_PreDeleteFunc = PreDelete |
||||||
|
|
||||||
|
async def PostDelete(a_CallbackQuery, a_ItemID): |
||||||
|
return await self.PostDelete(a_CallbackQuery, a_ItemID) |
||||||
|
self.m_PostDeleteFunc = PostDelete |
||||||
|
|
||||||
|
def AddBDItemFunc(a_ItemData, a_UserID): |
||||||
|
return self.AddBDItemFunc(a_ItemData, a_UserID) |
||||||
|
self.m_AddBDItemFunc = AddBDItemFunc |
||||||
|
|
||||||
|
def GetFSM(self, a_FSMName): |
||||||
|
return self.m_FSMs.get(a_FSMName, None) |
||||||
|
|
||||||
|
def GetInitBDCommands(self): |
||||||
|
return super(). GetInitBDCommands() + [ |
||||||
|
self.m_Table.GetInitTableRequest(), |
||||||
|
] |
||||||
|
|
||||||
|
def GetStartKeyboardButtons(self, a_Message, a_UserGroups): |
||||||
|
mod_buttons = super().GetStartKeyboardButtons(a_Message, a_UserGroups) |
||||||
|
cur_buttons = [ |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.LIST), user_access.AccessMode.VIEW, self.GetAccess()), |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.ADD), user_access.AccessMode.ADD, self.GetAccess()), |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.DEL), user_access.AccessMode.DELETE, self.GetAccess()), |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.EDIT), user_access.AccessMode.EDIT, self.GetAccess()), |
||||||
|
] |
||||||
|
return mod_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups) |
||||||
|
|
||||||
|
def GetEditKeyboardButtons(self, a_Message, a_UserGroups): |
||||||
|
mod_buttons = keyboard.MakeButtons(self.m_Bot, self.GetButtons(self.m_EditModuleNameList), a_UserGroups) |
||||||
|
cur_buttons = [ |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.EDIT_PHOTO), user_access.AccessMode.VIEW, self.GetAccess()), |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.EDIT_NAME), user_access.AccessMode.ADD, self.GetAccess()), |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.EDIT_DESC), user_access.AccessMode.DELETE, self.GetAccess()), |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.EDIT_ACCESS), user_access.AccessMode.DELETE, self.GetAccess()), |
||||||
|
keyboard.ButtonWithAccess(self.GetButton(ButtonNames.EDIT_DEFAULT_ACCESS), user_access.AccessMode.EDIT, self.GetAccess()), |
||||||
|
] |
||||||
|
return mod_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups) |
||||||
|
|
||||||
|
def GetViewItemInlineKeyboardTemplate(self, a_ItemID): |
||||||
|
def GetViewItemInlineKeyboard(a_Message, a_UserGroups): |
||||||
|
return self.GetViewItemInlineKeyboard(a_Message, a_UserGroups, a_ItemID) |
||||||
|
return GetViewItemInlineKeyboard |
||||||
|
|
||||||
|
def GetSelectPrefix(self): |
||||||
|
return self.m_SelectPrefix |
||||||
|
|
||||||
|
def GetViewItemInlineKeyboard(self, a_Message, a_UserGroups, a_ItemID): |
||||||
|
if not self.m_ChildModName: |
||||||
|
return None |
||||||
|
child_mod = self.GetModule(self.m_ChildModName) |
||||||
|
cur_buttons = [ |
||||||
|
keyboard.InlineButtonWithAccess(child_mod.GetButton(ButtonNames.LIST), child_mod.GetSelectPrefix(), a_ItemID, self.GetAccess(), user_access.AccessMode.VIEW), |
||||||
|
] |
||||||
|
return keyboard.MakeInlineKeyboardButtons(self.m_Bot, cur_buttons, a_UserGroups) |
||||||
|
|
||||||
|
def GetButtonNameAndKeyValueAndAccess(self, a_Item): |
||||||
|
return \ |
||||||
|
a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.NAME)],\ |
||||||
|
a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.KEY)],\ |
||||||
|
a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS)] |
||||||
|
|
||||||
|
def ShowMessageTemplate(self, a_Message, Inline_keyboard_template_func = None): |
||||||
|
async def ShowMessage(a_CallbackQuery, a_Item): |
||||||
|
msg = a_Message.StaticCopy() |
||||||
|
# TODO: добавить поддержку языка в a_MessageName |
||||||
|
Inline_keyboard_func = None |
||||||
|
item_access = None |
||||||
|
if a_Item: |
||||||
|
if len(a_Item) < self.m_Table.GetFieldsCount() - 1: # Для проектов это нужно. Там на 1 меньше поле. TODO разделить отправку сообщений item_access и Inline_keyboard_func |
||||||
|
return simple_message.WorkFuncResult(self.GetMessage(Messages.ERROR_FIND)) |
||||||
|
elif len(a_Item) == self.m_Table.GetFieldsCount(): |
||||||
|
lang = str(a_CallbackQuery.from_user.language_code) |
||||||
|
msg = msg.GetMessageForLang(lang).StaticCopy() |
||||||
|
msg.UpdateDesc(self.m_Table.ReplaceAllFieldTags(msg.GetDesc(), a_Item)) |
||||||
|
photo_field = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.PHOTO) |
||||||
|
if photo_field: |
||||||
|
msg.UpdatePhotoID(a_Item[photo_field]) |
||||||
|
item_access = a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS)] |
||||||
|
if Inline_keyboard_template_func: |
||||||
|
Inline_keyboard_func = Inline_keyboard_template_func(a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.KEY)]) |
||||||
|
|
||||||
|
return simple_message.WorkFuncResult(msg, item_access = item_access, Inline_keyboard_func = Inline_keyboard_func) |
||||||
|
return ShowMessage |
||||||
|
|
||||||
|
# TODO: delete? |
||||||
|
def SimpleMessageTemplate(self, a_MessageName : Messages): |
||||||
|
async def ShowMessage(a_CallbackQuery, a_Item): |
||||||
|
return simple_message.WorkFuncResult(self.GetMessage(a_MessageName)) |
||||||
|
return ShowMessage |
||||||
|
|
||||||
|
async def PreDelete(self, a_CallbackQuery, a_Item): |
||||||
|
if len(a_Item) < self.m_Table.GetFieldsCount(): |
||||||
|
return simple_message.WorkFuncResult(error_find_proj_message) |
||||||
|
access = a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS)] |
||||||
|
return simple_message.WorkFuncResult(self.GetMessage(Messages.SUCCESS_DELETE), None, item_access = access) |
||||||
|
|
||||||
|
async def PostDelete(self, a_CallbackQuery, a_ItemID): |
||||||
|
self.m_Log.Success(f'Задача №{a_ItemID} была удалена пользователем {a_CallbackQuery.from_user.id}.') |
||||||
|
#TODO: удалить вложенные |
||||||
|
self.OnChange() |
||||||
|
return simple_message.WorkFuncResult(self.GetMessage(Messages.SUCCESS_DELETE)) |
||||||
|
|
||||||
|
def AddBDItemFunc(self, a_ItemData, a_UserID): |
||||||
|
table_name = self.m_Table.GetName() |
||||||
|
name_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.NAME) |
||||||
|
photo_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PHOTO) |
||||||
|
desc_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.DESC) |
||||||
|
access_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.ACCESS) |
||||||
|
create_datetime_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.CREATE_DATE) |
||||||
|
parent_id_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PARENT_ID) |
||||||
|
|
||||||
|
res, error = None, None |
||||||
|
def_access = access_utils.GetItemDefaultAccessForModule(self.m_Bot, self.GetName()) |
||||||
|
#TODO сделать список полей, чтобы запрос генерировался автоматически. |
||||||
|
if parent_id_field: |
||||||
|
res, error = self.m_Bot.SQLRequest(f'INSERT INTO {table_name}({photo_field}, {name_field}, {desc_field}, {access_field}, {parent_id_field}, {create_datetime_field}) VALUES(?, ?, ?, ?, ?, {bot_bd.GetBDDateTimeNow()})', |
||||||
|
commit = True, return_error = True, param = (a_ItemData[photo_field], a_ItemData[name_field], a_ItemData[desc_field], def_access + f";{a_UserID}=+", a_ItemData[parent_id_field])) |
||||||
|
else: |
||||||
|
res, error = self.m_Bot.SQLRequest(f'INSERT INTO {table_name}({photo_field}, {name_field}, {desc_field}, {access_field}, {create_datetime_field}) VALUES(?, ?, ?, ?, {bot_bd.GetBDDateTimeNow()})', |
||||||
|
commit = True, return_error = True, param = (a_ItemData[photo_field], a_ItemData[name_field], a_ItemData[desc_field], def_access + f";{a_UserID}=+")) |
||||||
|
|
||||||
|
self.OnChange() |
||||||
|
if error: |
||||||
|
self.m_Log.Error(f'Пользоватлель {a_UserID}. Ошибка добавления записи в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {def_access}).') |
||||||
|
else: |
||||||
|
self.m_Log.Success(f'Пользоватлель {a_UserID}. Добавлена запись в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {def_access}).') |
||||||
|
|
||||||
|
return res, error |
||||||
|
|
||||||
|
def RegisterSelect(self, a_ButtonName, access_mode, only_parent = False): |
||||||
|
a_Prefix = None |
||||||
|
if self.m_ParentModName: |
||||||
|
parent_mod = self.GetModule(self.m_ParentModName) |
||||||
|
a_Prefix = parent_mod.RegisterSelect(a_ButtonName, access_mode, only_parent = False) |
||||||
|
if not only_parent: |
||||||
|
a_Prefix = bd_item_select.NextSelectBDItemRegisterHandlers(self.m_Bot, \ |
||||||
|
a_Prefix, \ |
||||||
|
self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PARENT_ID), \ |
||||||
|
self.m_Table.GetName(), \ |
||||||
|
self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.KEY), \ |
||||||
|
self.m_GetButtonNameAndKeyValueAndAccessFunc, \ |
||||||
|
self.GetMessage(Messages.SELECT), \ |
||||||
|
self.m_GetAccessFunc,\ |
||||||
|
access_mode = access_mode\ |
||||||
|
) |
||||||
|
else: |
||||||
|
if not only_parent: |
||||||
|
a_PrefixBase = a_ButtonName.GetDesc() |
||||||
|
a_Prefix = bd_item_select.FirstSelectBDItemRegisterHandlers(self.m_Bot, \ |
||||||
|
a_PrefixBase, \ |
||||||
|
a_ButtonName, \ |
||||||
|
self.m_Table.GetName(), \ |
||||||
|
self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.KEY), \ |
||||||
|
self.m_GetButtonNameAndKeyValueAndAccessFunc, \ |
||||||
|
self.GetMessage(Messages.SELECT), \ |
||||||
|
self.m_GetAccessFunc,\ |
||||||
|
access_mode = access_mode\ |
||||||
|
) |
||||||
|
return a_Prefix |
||||||
|
|
||||||
|
def RegisterHandlers(self): |
||||||
|
super().RegisterHandlers() |
||||||
|
table_name = self.m_Table.GetName() |
||||||
|
key_name = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.KEY) |
||||||
|
name_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.NAME) |
||||||
|
desc_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.DESC) |
||||||
|
photo_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PHOTO) |
||||||
|
access_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.ACCESS) |
||||||
|
def_access_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.DEFAULT_ACCESS) |
||||||
|
parent_id_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PARENT_ID) |
||||||
|
|
||||||
|
parent_table_name = None |
||||||
|
parent_key_name = None |
||||||
|
if self.m_ParentModName: |
||||||
|
parent_mod = self.GetModule(self.m_ParentModName) |
||||||
|
parent_table_name = parent_mod.m_Table.GetName() |
||||||
|
parent_key_name = parent_mod.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.KEY) |
||||||
|
|
||||||
|
def GetViewItemInlineKeyboardTemplate(a_ItemID): |
||||||
|
return self.GetViewItemInlineKeyboardTemplate(a_ItemID) |
||||||
|
|
||||||
|
GetButtonNameAndKeyValueAndAccess = self.m_GetButtonNameAndKeyValueAndAccessFunc |
||||||
|
GetAccess = self.m_GetAccessFunc |
||||||
|
|
||||||
|
defaul_keyboard_func = self.m_GetStartKeyboardButtonsFunc |
||||||
|
|
||||||
|
# Список |
||||||
|
a_ButtonName = self.GetButton(ButtonNames.LIST) |
||||||
|
if a_ButtonName: |
||||||
|
a_Prefix = self.RegisterSelect(a_ButtonName, user_access.AccessMode.VIEW, only_parent = True) |
||||||
|
if a_Prefix: |
||||||
|
bd_item_view.LastSelectAndShowBDItemRegisterHandlers(self.m_Bot, \ |
||||||
|
a_Prefix,\ |
||||||
|
parent_id_field, \ |
||||||
|
table_name,\ |
||||||
|
key_name, \ |
||||||
|
self.ShowMessageTemplate(self.GetMessage(Messages.OPEN), GetViewItemInlineKeyboardTemplate), \ |
||||||
|
GetButtonNameAndKeyValueAndAccess, \ |
||||||
|
self.GetMessage(Messages.SELECT), \ |
||||||
|
GetAccess, \ |
||||||
|
defaul_keyboard_func, \ |
||||||
|
access_mode = user_access.AccessMode.VIEW\ |
||||||
|
) |
||||||
|
else: |
||||||
|
bd_item_view.FirstSelectAndShowBDItemRegisterHandlers(self.m_Bot, \ |
||||||
|
a_ButtonName, \ |
||||||
|
table_name, \ |
||||||
|
key_name, \ |
||||||
|
self.ShowMessageTemplate(self.GetMessage(Messages.OPEN), GetViewItemInlineKeyboardTemplate), \ |
||||||
|
GetButtonNameAndKeyValueAndAccess, \ |
||||||
|
self.GetMessage(Messages.SELECT), \ |
||||||
|
GetAccess, \ |
||||||
|
defaul_keyboard_func\ |
||||||
|
) |
||||||
|
self.m_SelectPrefix = a_Prefix |
||||||
|
|
||||||
|
# Удаление |
||||||
|
a_ButtonName = self.GetButton(ButtonNames.DEL) |
||||||
|
if a_ButtonName: |
||||||
|
a_Prefix = self.RegisterSelect(a_ButtonName, user_access.AccessMode.DELETE) |
||||||
|
bd_item_delete.DeleteBDItemRegisterHandlers(self.m_Bot, \ |
||||||
|
a_Prefix, \ |
||||||
|
table_name, \ |
||||||
|
key_name, \ |
||||||
|
self.m_PreDeleteFunc, \ |
||||||
|
self.m_PostDeleteFunc, \ |
||||||
|
GetAccess, \ |
||||||
|
defaul_keyboard_func\ |
||||||
|
) |
||||||
|
|
||||||
|
# Добавление |
||||||
|
a_ButtonName = self.GetButton(ButtonNames.ADD) |
||||||
|
if a_ButtonName: |
||||||
|
a_Prefix = self.RegisterSelect(a_ButtonName, user_access.AccessMode.ADD, only_parent = True) |
||||||
|
|
||||||
|
check_func = bd_item.GetCheckForTextFunc(a_ButtonName) |
||||||
|
if a_Prefix: |
||||||
|
check_func = bd_item.GetCheckForPrefixFunc(a_Prefix) |
||||||
|
|
||||||
|
bd_item_add.AddBDItem3RegisterHandlers(self.m_Bot, \ |
||||||
|
check_func, \ |
||||||
|
self.GetFSM(FSMs.CREATE), \ |
||||||
|
self.GetFSM(FSMs.CREATE).name,\ |
||||||
|
self.GetFSM(FSMs.CREATE).desc, \ |
||||||
|
self.GetFSM(FSMs.CREATE).photo,\ |
||||||
|
self.m_AddBDItemFunc, \ |
||||||
|
self.ShowMessageTemplate(self.GetMessage(Messages.CREATE_NAME)), \ |
||||||
|
self.ShowMessageTemplate(self.GetMessage(Messages.CREATE_DESC)), \ |
||||||
|
self.ShowMessageTemplate(self.GetMessage(Messages.CREATE_PHOTO)), \ |
||||||
|
self.ShowMessageTemplate(self.GetMessage(Messages.SUCCESS_CREATE)), \ |
||||||
|
a_Prefix,\ |
||||||
|
parent_table_name, \ |
||||||
|
parent_key_name, \ |
||||||
|
name_field, \ |
||||||
|
desc_field, \ |
||||||
|
photo_field, \ |
||||||
|
GetButtonNameAndKeyValueAndAccess, \ |
||||||
|
GetAccess, \ |
||||||
|
self.m_GetStartKeyboardButtonsFunc\ |
||||||
|
) |
||||||
|
|
||||||
|
# Редактирование |
||||||
|
edit_keyboard_func = self.m_GetEditKeyboardButtonsFunc |
||||||
|
def RegisterEdit(a_ButtonName, a_FSM, a_EditMessage, a_FieldName, a_FieldType, a_AccessMode = user_access.AccessMode.EDIT): |
||||||
|
if not a_ButtonName: |
||||||
|
return |
||||||
|
|
||||||
|
def OnChange(): |
||||||
|
return self.OnChange() |
||||||
|
|
||||||
|
a_Prefix = self.RegisterSelect(a_ButtonName, a_AccessMode, only_parent = True) |
||||||
|
check_func = bd_item.GetCheckForTextFunc(a_ButtonName) |
||||||
|
if a_Prefix: |
||||||
|
check_func = bd_item.GetCheckForPrefixFunc(a_Prefix) |
||||||
|
#print(a_ButtonName, a_Prefix, check_func) |
||||||
|
bd_item_edit.EditBDItemRegisterHandlers(self.m_Bot, \ |
||||||
|
a_Prefix, \ |
||||||
|
a_FSM, \ |
||||||
|
check_func, \ |
||||||
|
self.GetMessage(Messages.SELECT_TO_EDIT), \ |
||||||
|
self.ShowMessageTemplate(a_EditMessage), \ |
||||||
|
self.ShowMessageTemplate(self.GetMessage(Messages.SUCCESS_EDIT)), \ |
||||||
|
table_name, \ |
||||||
|
key_name, \ |
||||||
|
parent_id_field, \ |
||||||
|
a_FieldName, \ |
||||||
|
GetButtonNameAndKeyValueAndAccess, \ |
||||||
|
GetAccess, \ |
||||||
|
edit_keyboard_func, \ |
||||||
|
OnChange,\ |
||||||
|
access_mode = a_AccessMode, \ |
||||||
|
field_type = a_FieldType\ |
||||||
|
) |
||||||
|
|
||||||
|
a_ButtonName = self.GetButton(ButtonNames.EDIT) |
||||||
|
if a_ButtonName: |
||||||
|
self.m_Bot.RegisterMessageHandler(\ |
||||||
|
simple_message.InfoMessageTemplate(\ |
||||||
|
self.m_Bot,\ |
||||||
|
self.GetMessage(Messages.START_EDIT),\ |
||||||
|
edit_keyboard_func,\ |
||||||
|
None,\ |
||||||
|
GetAccess,\ |
||||||
|
access_mode = user_access.AccessMode.EDIT),\ |
||||||
|
bd_item.GetCheckForTextFunc(a_ButtonName)\ |
||||||
|
) |
||||||
|
|
||||||
|
RegisterEdit(self.GetButton(ButtonNames.EDIT_NAME), self.GetFSM(FSMs.EDIT_NAME), self.GetMessage(Messages.EDIT_NAME), name_field, bd_item.FieldType.text) |
||||||
|
RegisterEdit(self.GetButton(ButtonNames.EDIT_DESC), self.GetFSM(FSMs.EDIT_DESC), self.GetMessage(Messages.EDIT_DESC), desc_field, bd_item.FieldType.text) |
||||||
|
RegisterEdit(self.GetButton(ButtonNames.EDIT_PHOTO), self.GetFSM(FSMs.EDIT_PHOTO), self.GetMessage(Messages.EDIT_PHOTO), photo_field, bd_item.FieldType.photo) |
||||||
|
RegisterEdit(self.GetButton(ButtonNames.EDIT_ACCESS), self.GetFSM(FSMs.EDIT_ACCESS), self.GetMessage(Messages.EDIT_ACCESS), access_field, bd_item.FieldType.text) |
||||||
|
RegisterEdit(self.GetButton(ButtonNames.EDIT_DEFAULT_ACCESS), self.GetFSM(FSMs.EDIT_DEFAULT_ACCESS), self.GetMessage(Messages.EDIT_DEFAULT_ACCESS), def_access_field, bd_item.FieldType.text) |
||||||
|
|
||||||
|
def OnChange(self): |
||||||
|
pass |
@ -0,0 +1,104 @@ |
|||||||
|
#-*-coding utf-8-*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
from bot_sys import interfaces, bot_bd, keyboard, user_access |
||||||
|
|
||||||
|
from aiogram import types |
||||||
|
from aiogram import Bot |
||||||
|
from aiogram.dispatcher import Dispatcher |
||||||
|
from aiogram.contrib.fsm_storage.memory import MemoryStorage |
||||||
|
from aiogram.utils import executor |
||||||
|
|
||||||
|
class AiogramBot(interfaces.IBot): |
||||||
|
def __init__(self, a_TelegramBotApiToken, a_BDFileName, a_RootIDs, a_Log): |
||||||
|
self.m_TelegramBotApiToken = a_TelegramBotApiToken |
||||||
|
self.m_BDFileName = a_BDFileName |
||||||
|
self.m_RootIDs = a_RootIDs |
||||||
|
self.m_Log = a_Log |
||||||
|
self.m_TBot = Bot(token=self.m_TelegramBotApiToken, parse_mode = types.ParseMode.HTML) |
||||||
|
self.m_Storage = MemoryStorage() |
||||||
|
self.m_Dispatcher = Dispatcher(self.m_TBot, storage = self.m_Storage) |
||||||
|
|
||||||
|
def GetRootIDs(self): |
||||||
|
return self.m_RootIDs |
||||||
|
|
||||||
|
def GetLog(self): |
||||||
|
return self.m_Log |
||||||
|
|
||||||
|
def SQLRequest(self, a_Request : str, commit = False, return_error = False, param = None): |
||||||
|
return bot_bd.SQLRequest(self.m_Log, self.m_BDFileName, a_Request, commit = commit, return_error = return_error, param = param) |
||||||
|
|
||||||
|
async def SendMessage(self, a_UserID, a_Message, a_PhotoIDs, a_KeyboardButtons, a_InlineKeyboardButtons, parse_mode = None): |
||||||
|
if not parse_mode: |
||||||
|
parse_mode = types.ParseMode.HTML |
||||||
|
inline_keyboards = None |
||||||
|
if a_InlineKeyboardButtons: |
||||||
|
inline_keyboards = keyboard.MakeAiogramInlineKeyboards(a_InlineKeyboardButtons) |
||||||
|
base_keyboards = None |
||||||
|
if a_KeyboardButtons: |
||||||
|
base_keyboards = [keyboard.MakeAiogramKeyboard(a_KeyboardButtons)] |
||||||
|
if inline_keyboards: |
||||||
|
base_keyboards = inline_keyboards |
||||||
|
if a_PhotoIDs and a_PhotoIDs != 0 and a_PhotoIDs != '0': |
||||||
|
if base_keyboards: |
||||||
|
for k in base_keyboards: |
||||||
|
await self.m_TBot.send_photo( |
||||||
|
a_UserID, |
||||||
|
a_PhotoIDs, |
||||||
|
a_Message, |
||||||
|
reply_markup = k |
||||||
|
) |
||||||
|
else: |
||||||
|
await self.m_TBot.send_photo( |
||||||
|
a_UserID, |
||||||
|
a_PhotoIDs, |
||||||
|
a_Message |
||||||
|
) |
||||||
|
else: |
||||||
|
#print('SendMessage', a_UserID, a_Message, a_PhotoIDs, a_InlineKeyboardButtons, a_KeyboardButtons, base_keyboard) |
||||||
|
if base_keyboards: |
||||||
|
for k in base_keyboards: |
||||||
|
await self.m_TBot.send_message( |
||||||
|
a_UserID, |
||||||
|
a_Message, |
||||||
|
reply_markup = k, |
||||||
|
parse_mode = parse_mode |
||||||
|
) |
||||||
|
else: |
||||||
|
await self.m_TBot.send_message( |
||||||
|
a_UserID, |
||||||
|
a_Message, |
||||||
|
parse_mode = parse_mode |
||||||
|
) |
||||||
|
|
||||||
|
async def SendDocument(self, a_UserID, a_Document, a_Caption, a_KeyboardButtons, a_InlineKeyboardButtons): |
||||||
|
inline_keyboard = None |
||||||
|
if a_InlineKeyboardButtons: |
||||||
|
inline_keyboard = keyboard.MakeAiogramInlineKeyboard(a_InlineKeyboardButtons) |
||||||
|
base_keyboard = None |
||||||
|
if a_KeyboardButtons: |
||||||
|
base_keyboard = keyboard.MakeAiogramKeyboard(a_KeyboardButtons) |
||||||
|
if inline_keyboard: |
||||||
|
base_keyboard = inline_keyboard |
||||||
|
await self.m_TBot.send_document( |
||||||
|
a_UserID, |
||||||
|
a_Document, |
||||||
|
caption = a_Caption, |
||||||
|
reply_markup = base_keyboard |
||||||
|
) |
||||||
|
|
||||||
|
def RegisterMessageHandler(self, a_MessageHandler, a_CheckFunc=None, commands=None, regexp=None, content_types=None, state=None): |
||||||
|
if a_CheckFunc: |
||||||
|
self.m_Dispatcher.register_message_handler(a_MessageHandler, a_CheckFunc, commands=commands, regexp=regexp, content_types=content_types, state=state) |
||||||
|
else: |
||||||
|
self.m_Dispatcher.register_message_handler(a_MessageHandler, commands=commands, regexp=regexp, content_types=content_types, state=state) |
||||||
|
|
||||||
|
def RegisterCallbackHandler(self, a_CallbackHandler, a_CheckFunc=None, commands=None, regexp=None, content_types=None, state=None): |
||||||
|
if a_CheckFunc: |
||||||
|
self.m_Dispatcher.register_callback_query_handler(a_CallbackHandler, a_CheckFunc, commands=commands, regexp=regexp, content_types=content_types, state=state) |
||||||
|
else: |
||||||
|
self.m_Dispatcher.register_callback_query_handler(a_CallbackHandler, commands=commands, regexp=regexp, content_types=content_types, state=state) |
||||||
|
|
||||||
|
def StartPolling(self): |
||||||
|
executor.start_polling(self.m_Dispatcher) |
||||||
|
|
@ -0,0 +1,125 @@ |
|||||||
|
#-*-coding utf-8-*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
from enum import Enum |
||||||
|
from enum import auto |
||||||
|
|
||||||
|
# Тип поля в таблице |
||||||
|
class TableFieldType(Enum): |
||||||
|
INT = 'INTEGER' |
||||||
|
STR = 'TEXT' |
||||||
|
|
||||||
|
# Предназначение поля в таблице |
||||||
|
class TableFieldDestiny(Enum): |
||||||
|
KEY = auto() |
||||||
|
NAME = auto() |
||||||
|
DESC = auto() |
||||||
|
PHOTO = auto() |
||||||
|
ACCESS = auto() |
||||||
|
DEFAULT_ACCESS = auto() |
||||||
|
CREATE_DATE = auto() |
||||||
|
PARENT_ID = auto() |
||||||
|
OTHER = auto() |
||||||
|
|
||||||
|
class TableField: |
||||||
|
def __init__(self, a_Name, a_Destiny : TableFieldDestiny, a_Type : TableFieldType): |
||||||
|
self.m_Name = a_Name |
||||||
|
self.m_Destiny = a_Destiny |
||||||
|
self.m_Type = a_Type |
||||||
|
|
||||||
|
class Table: |
||||||
|
def __init__(self, a_TableName, a_Fields : [TableField], a_UniqueFields = None): |
||||||
|
self.m_TableName = a_TableName |
||||||
|
self.m_Fields = a_Fields |
||||||
|
self.m_UniqueFields = a_UniqueFields |
||||||
|
|
||||||
|
def GetName(self): |
||||||
|
return self.m_TableName |
||||||
|
|
||||||
|
def GetFields(self): |
||||||
|
return self.TableFieldType |
||||||
|
|
||||||
|
def GetFieldsCount(self): |
||||||
|
return len(self.m_Fields) |
||||||
|
|
||||||
|
def GetFieldByDestiny(self, a_Destiny): |
||||||
|
for f in self.m_Fields: |
||||||
|
if f.m_Destiny == a_Destiny: |
||||||
|
return f |
||||||
|
return None |
||||||
|
|
||||||
|
def GetFieldNameByDestiny(self, a_Destiny): |
||||||
|
f = self.GetFieldByDestiny(a_Destiny) |
||||||
|
if f: |
||||||
|
return f.m_Name |
||||||
|
return None |
||||||
|
|
||||||
|
def GetFieldIDByDestiny(self, a_Destiny): |
||||||
|
for i in range(len(self.m_Fields)): |
||||||
|
f = self.m_Fields[i] |
||||||
|
if f.m_Destiny == a_Destiny: |
||||||
|
return i |
||||||
|
return None |
||||||
|
|
||||||
|
def GetInitTableRequest(self): |
||||||
|
request = f'CREATE TABLE IF NOT EXISTS {self.GetName()}(' |
||||||
|
items = [] |
||||||
|
for f in self.m_Fields: |
||||||
|
item = f.m_Name + ' ' + str(f.m_Type.value) |
||||||
|
if f.m_Destiny == TableFieldDestiny.KEY: |
||||||
|
item += ' PRIMARY KEY' |
||||||
|
items += [item] |
||||||
|
if self.m_UniqueFields: |
||||||
|
for u in self.m_UniqueFields: |
||||||
|
fields = [] |
||||||
|
for f in u: |
||||||
|
fields += [f.m_Name] |
||||||
|
items += ['UNIQUE(' + ', '.join(fields) +')'] |
||||||
|
return request + ', '.join(items) + ');' |
||||||
|
|
||||||
|
def ReplaceAllFieldTags(self, a_String, a_BDItem): |
||||||
|
result = a_String |
||||||
|
for i in range(len(self.m_Fields)): |
||||||
|
f = self.m_Fields[i] |
||||||
|
result = result.replace(f'#{f.m_Name}', str(a_BDItem[i])) |
||||||
|
return result |
||||||
|
|
||||||
|
def Test(): |
||||||
|
f1 = TableField('f1', TableFieldDestiny.KEY, TableFieldType.INT) |
||||||
|
f2 = TableField('f2', TableFieldDestiny.NAME, TableFieldType.STR) |
||||||
|
f3 = TableField('f3', TableFieldDestiny.DESC, TableFieldType.STR) |
||||||
|
table = Table('tname', [ |
||||||
|
f1, |
||||||
|
f2, |
||||||
|
f3 |
||||||
|
], |
||||||
|
[[f1], [f2, f3]] |
||||||
|
) |
||||||
|
assert table.GetName() == 'tname' |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.KEY).m_Name == 'f1' |
||||||
|
assert table.GetFieldNameByDestiny(TableFieldDestiny.KEY) == 'f1' |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.KEY).m_Destiny == TableFieldDestiny.KEY |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.KEY).m_Type == TableFieldType.INT |
||||||
|
assert table.GetFieldIDByDestiny(TableFieldDestiny.KEY) == 0 |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.NAME).m_Name == 'f2' |
||||||
|
assert table.GetFieldNameByDestiny(TableFieldDestiny.NAME) == 'f2' |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.NAME).m_Destiny == TableFieldDestiny.NAME |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.NAME).m_Type == TableFieldType.STR |
||||||
|
assert table.GetFieldIDByDestiny(TableFieldDestiny.NAME) == 1 |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.DESC).m_Name == 'f3' |
||||||
|
assert table.GetFieldNameByDestiny(TableFieldDestiny.DESC) == 'f3' |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.DESC).m_Destiny == TableFieldDestiny.DESC |
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.DESC).m_Type == TableFieldType.STR |
||||||
|
assert table.GetFieldIDByDestiny(TableFieldDestiny.DESC) == 2 |
||||||
|
|
||||||
|
assert table.GetFieldByDestiny(TableFieldDestiny.PHOTO) == None |
||||||
|
assert table.GetFieldIDByDestiny(TableFieldDestiny.PHOTO) == None |
||||||
|
assert table.GetFieldNameByDestiny(TableFieldDestiny.PHOTO) == None |
||||||
|
|
||||||
|
assert table.GetFieldsCount() == 3 |
||||||
|
|
||||||
|
print(table.GetInitTableRequest()) |
||||||
|
assert table.GetInitTableRequest() == 'CREATE TABLE IF NOT EXISTS tname(f1 INTEGER PRIMARY KEY, f2 TEXT, f3 TEXT, UNIQUE(f1), UNIQUE(f2, f3));' |
||||||
|
|
||||||
|
item = [10, 'i1', 'i2'] |
||||||
|
assert table.ReplaceAllFieldTags('#f1 #f2 #f3', item) == '10 i1 i2' |
@ -0,0 +1,83 @@ |
|||||||
|
#-*-coding utf-8-*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
# Работа с сообщениями |
||||||
|
|
||||||
|
class BotMessage: |
||||||
|
def __init__(self, a_BotMessages, a_MessageName : str, a_MessageDesc : str, a_Language : str, a_PhotoID : str, a_DateTime): |
||||||
|
self.m_BotMessages = a_BotMessages |
||||||
|
self.m_MessageName = a_MessageName |
||||||
|
self.m_MessageDesc = a_MessageDesc |
||||||
|
self.m_Language = a_Language |
||||||
|
self.m_PhotoID = a_PhotoID |
||||||
|
self.m_DateTime = a_DateTime |
||||||
|
|
||||||
|
def StaticCopy(self): |
||||||
|
return BotMessage(None, self.m_MessageName, self.m_MessageDesc, self.m_Language, self.m_PhotoID, self.m_DateTime) |
||||||
|
|
||||||
|
def GetName(self): |
||||||
|
return self.m_MessageName |
||||||
|
|
||||||
|
def GetDesc(self): |
||||||
|
return self.m_MessageDesc |
||||||
|
|
||||||
|
def UpdateDesc(self, a_Desc): |
||||||
|
self.m_MessageDesc = a_Desc |
||||||
|
|
||||||
|
def GetLanguage(self): |
||||||
|
return self.m_Language |
||||||
|
|
||||||
|
def GetPhotoID(self): |
||||||
|
return self.m_PhotoID |
||||||
|
|
||||||
|
def UpdatePhotoID(self, a_PhotoID): |
||||||
|
self.m_PhotoID = a_PhotoID |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
msg = self.GetMessageForLang(self.m_Language) |
||||||
|
return msg.GetDesc() |
||||||
|
|
||||||
|
def GetMessageForLang(self, a_Language): |
||||||
|
if not self.m_BotMessages: |
||||||
|
return self |
||||||
|
last_update = self.m_BotMessages.m_LastUpdate |
||||||
|
new_msg = self |
||||||
|
if self.m_DateTime < last_update: |
||||||
|
msg = self.m_BotMessages.GetMessages() |
||||||
|
if not msg.get(a_Language, None): |
||||||
|
a_Language = self.m_Language |
||||||
|
if not msg.get(a_Language, None): |
||||||
|
a_Language = self.m_BotMessages.a_DefaultLanguage |
||||||
|
new_msg = msg[a_Language].get(self.m_MessageName, self) |
||||||
|
if a_Language == self.m_Language: |
||||||
|
self.m_MessageDesc = new_msg.m_MessageDesc |
||||||
|
self.m_Language = new_msg.m_Language |
||||||
|
self.m_PhotoID = new_msg.m_PhotoID |
||||||
|
self.m_DateTime = new_msg.m_DateTime |
||||||
|
return new_msg |
||||||
|
|
||||||
|
def MakeBotMessage(a_MessageDesc): |
||||||
|
return BotMessage(None, '', a_MessageDesc, None, 0, None) |
||||||
|
|
||||||
|
class BotMessages: |
||||||
|
def __init__(self, a_DefaultLanguage): |
||||||
|
self.m_DefaultLanguage = a_DefaultLanguage |
||||||
|
self.m_Messages = {} |
||||||
|
self.m_LastUpdate = None |
||||||
|
|
||||||
|
def GetMessages(self): |
||||||
|
return self.m_Messages |
||||||
|
|
||||||
|
def UpdateSignal(self, a_DateTime): |
||||||
|
self.m_LastUpdate = a_DateTime |
||||||
|
|
||||||
|
def CreateMessage(self, a_MessageName, a_MessageDesc, a_DateTime, a_MessagePhotoID = 0, a_MessageLang = None): |
||||||
|
if not a_MessageLang: |
||||||
|
a_MessageLang = self.m_DefaultLanguage |
||||||
|
cur_msg = BotMessage(self, a_MessageName, a_MessageDesc, a_MessageLang, a_MessagePhotoID, a_DateTime) |
||||||
|
msg = self.GetMessages() |
||||||
|
if not msg.get(a_MessageLang, None): |
||||||
|
msg[a_MessageLang] = {} |
||||||
|
msg[a_MessageLang][a_MessageName] = cur_msg |
||||||
|
return cur_msg |
||||||
|
|
@ -0,0 +1,38 @@ |
|||||||
|
#-*-coding utf-8-*- |
||||||
|
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
||||||
|
|
||||||
|
from abc import ABC, abstractmethod |
||||||
|
|
||||||
|
class IBot(ABC): |
||||||
|
@abstractmethod |
||||||
|
def GetRootIDs(self): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def GetLog(self): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def SQLRequest(self, a_Request : str, commit = False, return_error = False, param = None): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
async def SendMessage(self, a_UserID, a_Message, a_PhotoIDs, a_KeyboardButtons, a_InlineKeyboardButtons, parse_mode=None): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
async def SendDocument(self, a_UserID, a_Document, a_Caption, a_KeyboardButtons, a_InlineKeyboardButtons): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def RegisterMessageHandler(self, a_MessageHandler, a_CheckFunc=None, commands=None, regexp=None, content_types=None, state=None): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def RegisterCallbackHandler(self, a_CallbackHandler, a_CheckFunc=None, commands=None, regexp=None, content_types=None, state=None): |
||||||
|
pass |
||||||
|
|
||||||
|
@abstractmethod |
||||||
|
def StartPolling(self): |
||||||
|
pass |
||||||
|
|
@ -1,56 +0,0 @@ |
|||||||
#-*-coding utf-8-*- |
|
||||||
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> |
|
||||||
|
|
||||||
import sqlite3 |
|
||||||
from bot_sys import log |
|
||||||
|
|
||||||
# Работа ссообщениями |
|
||||||
|
|
||||||
default_language = 'ru' |
|
||||||
|
|
||||||
g_messages = None |
|
||||||
def GetMessages(): |
|
||||||
global g_messages |
|
||||||
if not g_messages: |
|
||||||
g_messages = {} |
|
||||||
return g_messages |
|
||||||
|
|
||||||
g_last_update = None |
|
||||||
def UpdateSignal(a_DateTime): |
|
||||||
global g_last_update |
|
||||||
g_last_update = a_DateTime |
|
||||||
# --------------------------------------------------------- |
|
||||||
# Функции работы с собщениями |
|
||||||
|
|
||||||
# --------------------------------------------------------- |
|
||||||
class Message: |
|
||||||
def __init__(self, a_MessageName : str, a_MessageDesc : str, a_Language : str, a_PhotoID : str, a_DateTime): |
|
||||||
self.m_MessageName = a_MessageName |
|
||||||
self.m_MessageDesc = a_MessageDesc |
|
||||||
self.m_Language = a_Language |
|
||||||
self.m_PhotoID = a_PhotoID |
|
||||||
self.m_DateTime = a_DateTime |
|
||||||
|
|
||||||
def __str__(self): |
|
||||||
global g_last_update |
|
||||||
last_update = g_last_update |
|
||||||
if self.m_DateTime < last_update: |
|
||||||
msg = GetMessages() |
|
||||||
if not msg.get(self.m_Language, None): |
|
||||||
msg[self.m_Language] = {} |
|
||||||
new_msg = msg[self.m_Language].get(self.m_MessageName, self) |
|
||||||
self.m_MessageName = new_msg.m_MessageName |
|
||||||
self.m_MessageDesc = new_msg.m_MessageDesc |
|
||||||
self.m_PhotoID = new_msg.m_PhotoID |
|
||||||
self.m_DateTime = last_update |
|
||||||
return f'{self.m_MessageDesc}' |
|
||||||
|
|
||||||
def MSG(a_MessageName, a_MessageDesc, a_UpdateMSG, a_DateTime): |
|
||||||
cur_msg = Message(a_MessageName, a_MessageDesc, default_language, 0, a_DateTime) |
|
||||||
msg = GetMessages() |
|
||||||
if not msg.get(default_language, None): |
|
||||||
msg[default_language] = {} |
|
||||||
if not msg[default_language].get(a_MessageName, None): |
|
||||||
msg[default_language][a_MessageName] = cur_msg |
|
||||||
a_UpdateMSG(cur_msg) |
|
||||||
|
|
Loading…
Reference in new issue