to_local_var #2

Merged
Bezborodov merged 25 commits from to_local_var into master 2 years ago
  1. 220
      bot_modules/access.py
  2. 37
      bot_modules/access_utils.py
  3. 124
      bot_modules/backup.py
  4. 200
      bot_modules/buttons.py
  5. 396
      bot_modules/comments.py
  6. 156
      bot_modules/groups.py
  7. 16
      bot_modules/groups_utils.py
  8. 421
      bot_modules/languages.py
  9. 451
      bot_modules/messages.py
  10. 15
      bot_modules/mod_agregator.py
  11. 25
      bot_modules/mod_interface.py
  12. 112
      bot_modules/mod_simple_message.py
  13. 386
      bot_modules/mod_table_operate.py
  14. 384
      bot_modules/needs.py
  15. 136
      bot_modules/profile.py
  16. 352
      bot_modules/projects.py
  17. 104
      bot_modules/start.py
  18. 371
      bot_modules/tasks.py
  19. 104
      bot_sys/aiogram_bot.py
  20. 125
      bot_sys/bd_table.py
  21. 30
      bot_sys/bot_bd.py
  22. 83
      bot_sys/bot_messages.py
  23. 38
      bot_sys/interfaces.py
  24. 65
      bot_sys/keyboard.py
  25. 82
      bot_sys/log.py
  26. 218
      bot_sys/user_access.py
  27. 56
      bot_sys/user_messages.py
  28. 122
      main.py
  29. 51
      template/bd_item.py
  30. 78
      template/bd_item_add.py
  31. 31
      template/bd_item_delete.py
  32. 40
      template/bd_item_edit.py
  33. 32
      template/bd_item_select.py
  34. 24
      template/bd_item_view.py
  35. 39
      template/file_message.py
  36. 73
      template/simple_message.py
  37. 65
      template/sql_request.py

220
bot_modules/access.py

@ -3,49 +3,39 @@
# Права пользователей
from bot_sys import bot_bd, log, config, keyboard, user_access
from bot_modules import start, groups
from template import simple_message, sql_request, bd_item_edit, bd_item
from bot_sys import keyboard, user_access, bot_bd, bd_table
from bot_modules import mod_simple_message, access_utils, mod_table_operate
from template import simple_message, sql_request, bd_item
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.dispatcher import Dispatcher
from aiogram import types
class FSMRequestToBDAccess(StatesGroup):
sqlRequest = State()
class FSMEditAccessItem(StatesGroup):
item_field = State()
class FSMEditDefaultAccessItem(StatesGroup):
item_field = State()
# ---------------------------------------------------------
# БД
module_name = 'access'
table_name = 'module_access'
mod_name_field = 'modName'
moduleaccess_field = 'modAccess'
mod_default_access_field = 'itemDefaultAccess'
#TODO: Автоматическое создание init_bd_cmds, необходимо table_name, mod_name_field ... объединить в объект
init_bd_cmds = [f"""CREATE TABLE IF NOT EXISTS {table_name}(
{mod_name_field} TEXT,
{moduleaccess_field} TEXT,
{mod_default_access_field} TEXT,
UNIQUE({mod_name_field})
);""",
f"INSERT OR IGNORE INTO {table_name} ({mod_name_field}, {moduleaccess_field}, {mod_default_access_field}) VALUES ('{module_name}', '{user_access.user_access_group_new}=-', '{user_access.user_access_group_new}=-');"
]
table_name = access_utils.table_name
mod_name_field = access_utils.mod_name_field
moduleaccess_field = access_utils.moduleaccess_field
mod_default_access_field = access_utils.mod_default_access_field
table = bd_table.Table(table_name, [
bd_table.TableField(mod_name_field, bd_table.TableFieldDestiny.KEY, bd_table.TableFieldType.STR),
bd_table.TableField(moduleaccess_field, bd_table.TableFieldDestiny.ACCESS, bd_table.TableFieldType.STR),
bd_table.TableField(mod_default_access_field, bd_table.TableFieldDestiny.DEFAULT_ACCESS, bd_table.TableFieldType.STR),
])
# ---------------------------------------------------------
# Сообщения
access_start_message = '''
start_message = '''
<b> Права пользователей находятся в стадии разработки</b>
Пока можете воспользоваться хардкорным способом через запросы к БД
@ -68,11 +58,7 @@ help_message = '''
modAccess - строка
''' + user_access.user_access_readme
access_denied_message = '''
Доступ запрещён!
'''
access_button_name = "⛀ Доступ пользователей"
start_button_name = "⛀ Доступ пользователей"
sql_request_button_name = "⛁ Запрос к БД для редактирования доступа"
help_button_name = "📄 Информация по редактированию доступа"
@ -92,7 +78,7 @@ moduleaccess_edit_access_message = f'''
Введите новую строку доступа:
'''
edit_moduleaccess_default_access_button_name = "◈ Изменить доступ по умолчанию к модулю "
edit_moduleaccess_default_access_button_name = "◈ Изменить доступ по умолчанию"
moduleaccess_edit_default_access_message = f'''
Текущий доступ по умолчанию к модулю #{mod_name_field}:
#{mod_default_access_field}
@ -101,106 +87,80 @@ moduleaccess_edit_default_access_message = f'''
Введите новую строку доступа:
'''
moduleaccess_success_edit_message = '''✅ Доступ к модулю успешно отредактирован!'''
button_names = {
mod_simple_message.ButtonNames.START: start_button_name,
mod_table_operate.ButtonNames.EDIT: "🛠 Редактировать доступ",
mod_table_operate.ButtonNames.EDIT_ACCESS: edit_moduleaccess_access_button_name,
mod_table_operate.ButtonNames.EDIT_DEFAULT_ACCESS: edit_moduleaccess_default_access_button_name,
}
messages = {
mod_simple_message.Messages.START: start_message,
mod_table_operate.Messages.START_EDIT: '''
Пожалуйста, выберите действие:
''',
mod_table_operate.Messages.SELECT_TO_EDIT: moduleaccess_select_to_edit_message,
mod_table_operate.Messages.EDIT_ACCESS: moduleaccess_edit_access_message,
mod_table_operate.Messages.EDIT_DEFAULT_ACCESS: moduleaccess_edit_default_access_message,
mod_table_operate.Messages.SUCCESS_EDIT: moduleaccess_success_edit_message,
}
fsm = {
mod_table_operate.FSMs.EDIT_ACCESS: FSMEditAccessItem,
mod_table_operate.FSMs.EDIT_DEFAULT_ACCESS: FSMEditDefaultAccessItem,
}
init_access = f'{user_access.user_access_group_new}=-'
class ModuleAccess(mod_table_operate.TableOperateModule):
def __init__(self, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log):
super().__init__(table, messages, button_names, fsm, None, None, init_access, a_ChildModuleNameList, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log)
self.m_SqlRequestButtonName = self.CreateButton('sql request', sql_request_button_name)
self.m_RequestStartMessage = self.CreateMessage('equest start', request_start_message)
self.m_HelpButtonName = self.CreateButton('help', help_button_name)
self.m_HelpMessage = self.CreateMessage('help', help_message)
self.m_HelpMessageHandler = simple_message.InfoMessageTemplate(
self.m_Bot,
self.m_HelpMessage,
self.m_GetStartKeyboardButtonsFunc,
None,
self.m_GetAccessFunc
)
moduleaccess_success_edit_message = '''✅ Проект успешно отредактирован!'''
# ---------------------------------------------------------
# Работа с кнопками
def GetEditAccessKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(sql_request_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_moduleaccess_access_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_moduleaccess_default_access_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
keyboard.ButtonWithAccess(help_button_name, user_access.AccessMode.VIEW, GetAccess())
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
# ---------------------------------------------------------
# Обработка сообщений
def GetButtonNameAndKeyValueAndAccess(a_Item):
# ButtonName KeyValue Access
return a_Item[0], a_Item[0], a_Item[1]
def ShowMessageTemplate(a_StringMessage):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 3):
return simple_message.WorkFuncResult(error_find_proj_message)
msg = a_StringMessage.\
replace(f'#{mod_name_field}', a_Item[0]).\
replace(f'#{moduleaccess_field}', a_Item[1]).\
replace(f'#{mod_default_access_field}', a_Item[2])
return simple_message.WorkFuncResult(msg, item_access = a_Item[1])
return ShowMessage
def SimpleMessageTemplate(a_StringMessage):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery):
return simple_message.WorkFuncResult(a_StringMessage)
return ShowMessage
# ---------------------------------------------------------
# Работа с базой данных
def GetModuleAccessList():
return bot_bd.SelectBDTemplate(table_name)()
# ---------------------------------------------------------
# API
def GetAccessForModule(a_ModuleName):
alist = GetModuleAccessList()
for i in alist:
if i[0] == a_ModuleName:
return i[1]
return ''
def GetItemDefaultAccessForModule(a_ModuleName):
alist = GetModuleAccessList()
for i in alist:
if i[0] == a_ModuleName:
return i[2]
return ''
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [keyboard.ButtonWithAccess(access_button_name, user_access.AccessMode.VIEW, GetAccess())]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
defaul_keyboard_func = GetEditAccessKeyboardButtons
dp.register_message_handler(simple_message.InfoMessageTemplate(access_start_message, defaul_keyboard_func, GetAccess), text = access_button_name)
dp.register_message_handler(simple_message.InfoMessageTemplate(help_message, defaul_keyboard_func, GetAccess), text = help_button_name)
sql_request.RequestToBDRegisterHandlers(dp, sql_request_button_name, request_start_message, FSMRequestToBDAccess, defaul_keyboard_func, user_access.AccessMode.ACCEES_EDIT, GetAccess)
edit_keyboard_func = defaul_keyboard_func
def RegisterEdit(a_ButtonName, a_FSM, a_EditMessage, a_FieldName, a_FieldType, a_AccessMode = user_access.AccessMode.ACCEES_EDIT):
bd_item_edit.EditBDItemRegisterHandlers(dp, \
None, \
a_FSM, \
bd_item.GetCheckForTextFunc(a_ButtonName), \
moduleaccess_select_to_edit_message, \
ShowMessageTemplate(a_EditMessage), \
ShowMessageTemplate(moduleaccess_success_edit_message), \
table_name, \
mod_name_field, \
None, \
a_FieldName, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
edit_keyboard_func, \
access_mode = a_AccessMode, \
field_type = a_FieldType\
def GetButtonNameAndKeyValueAndAccess(self, a_Item):
return \
a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.KEY)],\
a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.KEY)],\
a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS)]
def GetName(self):
return module_name
def GetStartKeyboardButtons(self, a_Message, a_UserGroups):
mod_buttons = super().GetStartKeyboardButtons(a_Message, a_UserGroups)
cur_buttons = [
keyboard.ButtonWithAccess(self.m_SqlRequestButtonName, user_access.AccessMode.EDIT, self.GetAccess()),
keyboard.ButtonWithAccess(self.m_HelpButtonName , user_access.AccessMode.VIEW, self.GetAccess())
]
return mod_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups)
def RegisterHandlers(self):
super().RegisterHandlers()
sql_request.RequestToBDRegisterHandlers(
self.m_Bot,
self.m_SqlRequestButtonName,
self.m_RequestStartMessage,
FSMRequestToBDAccess,
self.m_GetStartKeyboardButtonsFunc,
user_access.AccessMode.EDIT,
self.m_GetAccessFunc
)
RegisterEdit(edit_moduleaccess_access_button_name, FSMEditAccessItem, moduleaccess_edit_access_message, moduleaccess_field, bd_item.FieldType.text, user_access.AccessMode.ACCEES_EDIT)
RegisterEdit(edit_moduleaccess_default_access_button_name, FSMEditDefaultAccessItem, moduleaccess_edit_default_access_message, mod_default_access_field, bd_item.FieldType.text, user_access.AccessMode.EDIT)
self.m_Bot.RegisterMessageHandler(
self.m_HelpMessageHandler,
bd_item.GetCheckForTextFunc(self.m_HelpButtonName)
)

37
bot_modules/access_utils.py

@ -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 ''

124
bot_modules/backup.py

@ -3,33 +3,22 @@
# Бэкапы пользователя
from bot_sys import bot_bd, log, config, keyboard, user_access
from bot_modules import start, access, groups
from template import file_message, simple_message
from aiogram import Bot, types
import sqlite3
from aiogram.dispatcher import Dispatcher
bot = Bot(token=config.GetTelegramBotApiToken(), parse_mode=types.ParseMode.HTML)
from bot_sys import user_access, keyboard
from bot_modules import mod_simple_message, profile
from template import bd_item, file_message
# ---------------------------------------------------------
# БД
module_name = 'backup'
init_bd_cmds = [
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_new}=-', '{user_access.user_access_group_new}=-');"
]
# ---------------------------------------------------------
# Сообщения
backup_message = '''
start_message = '''
<b>Здесь вы можете выполнить специальные операции по сервисному обслуживанию</b>
'''
start_button_name = "📦 Резервные копии и логи"
backup_bd_message = '''
<b>📀 Резервная копия базы данных</b>
🕰 <code>@time</code>
@ -44,44 +33,69 @@ error_backup_message = '''
<b> Ошибка резервного копирования</b>
'''
backup_button_name = "📦 Резервные копии и логи"
backup_bd_button_name = "📀 Резервные копия базы"
backup_log_button_name = "📃 Логи"
# ---------------------------------------------------------
# Работа с кнопками
def GetBackupKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(backup_bd_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(backup_log_button_name, user_access.AccessMode.EDIT, GetAccess())
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
# ---------------------------------------------------------
# Обработка сообщений
# ---------------------------------------------------------
# Работа с базой данных пользователей
# ---------------------------------------------------------
# API
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [keyboard.ButtonWithAccess(backup_button_name, user_access.AccessMode.VIEW, GetAccess())]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
dp.register_message_handler(simple_message.InfoMessageTemplate(backup_message, GetBackupKeyboardButtons, GetAccess), text = backup_button_name)
dp.register_message_handler(file_message.BackupFileTemplate(bot_bd.GetBDFileName(), backup_bd_message, GetAccess, GetBackupKeyboardButtons, error_backup_message), text = backup_bd_button_name)
dp.register_message_handler(file_message.BackupFileTemplate(log.g_log_file_name, backup_log_message, GetAccess, GetBackupKeyboardButtons, error_backup_message), text = backup_log_button_name)
button_names = {
mod_simple_message.ButtonNames.START: start_button_name,
}
messages = {
mod_simple_message.Messages.START: start_message,
}
init_access = f'{user_access.user_access_group_new}=-'
class ModuleBackup(mod_simple_message.SimpleMessageModule):
def __init__(self, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log):
super().__init__(messages, button_names, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log)
self.m_BackupBDButtonName = self.CreateButton('backup bd', backup_bd_button_name)
self.m_BackupBDMessage = self.CreateMessage('backup bd', backup_bd_message)
self.m_BackupLogButtonName = self.CreateButton('backup log', backup_log_button_name)
self.m_BackupLogMessage = self.CreateMessage('backup log', backup_log_message)
self.m_BackupErrorMessage = self.CreateMessage('backup error', error_backup_message)
self.m_BackupBDMessageHandler = file_message.BackupFileTemplate(
self.m_Bot,
self.m_Bot.m_BDFileName,
self.m_BackupBDMessage,
self.m_GetAccessFunc,
self.m_GetStartKeyboardButtonsFunc,
None,
self.m_BackupErrorMessage,
access_mode = user_access.AccessMode.EDIT
)
self.m_BackupLogMessageHandler = file_message.BackupFileTemplate(
self.m_Bot,
self.m_Bot.GetLog().GetFileName(),
self.m_BackupLogMessage,
self.m_GetAccessFunc,
self.m_GetStartKeyboardButtonsFunc,
None,
self.m_BackupErrorMessage,
access_mode = user_access.AccessMode.EDIT
)
def GetName(self):
return module_name
def GetStartKeyboardButtons(self, a_Message, a_UserGroups):
mod_buttons = super().GetStartKeyboardButtons(a_Message, a_UserGroups)
cur_buttons = [
keyboard.ButtonWithAccess(self.m_BackupBDButtonName, user_access.AccessMode.EDIT, self.GetAccess()),
keyboard.ButtonWithAccess(self.m_BackupLogButtonName , user_access.AccessMode.EDIT, self.GetAccess())
]
return mod_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups)
def RegisterHandlers(self):
super().RegisterHandlers()
self.m_Bot.RegisterMessageHandler(
self.m_BackupBDMessageHandler,
bd_item.GetCheckForTextFunc(self.m_BackupBDButtonName)
)
self.m_Bot.RegisterMessageHandler(
self.m_BackupLogMessageHandler,
bd_item.GetCheckForTextFunc(self.m_BackupLogButtonName)
)

200
bot_modules/buttons.py

@ -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()

396
bot_modules/comments.py

@ -3,26 +3,27 @@
# Комментарии
from bot_sys import bot_bd, log, keyboard, user_access
from bot_modules import start, access, groups, projects, tasks, needs
from template import bd_item_view, simple_message, bd_item_delete, bd_item_edit, bd_item, bd_item_add, bd_item_select
from aiogram import types
from bot_sys import bot_bd, keyboard, user_access, bd_table
from bot_modules import mod_table_operate, mod_simple_message
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.dispatcher import Dispatcher
import sqlite3
class FSMCreateComment(StatesGroup):
bd_item = State()
name = State()
desc = State()
photo = State()
class FSMEditCommentPhotoItem(StatesGroup):
item_field = State()
class FSMEditCommentNameItem(StatesGroup):
item_field = State()
class FSMEditCommentDescItem(StatesGroup):
item_id = State()
item_field = State()
class FSMEditCommentAccessItem(StatesGroup):
item_id = State()
item_field = State()
# ---------------------------------------------------------
# БД
@ -30,302 +31,123 @@ module_name = 'comments'
table_name = module_name
key_name = 'commentID'
name_field = 'commentName'
desc_field = 'commentDesc'
photo_field = 'commentPhoto'
access_field = 'commentAccess'
create_datetime_field = 'commentCreateDateTime'
parent_id_field = 'needID'
init_bd_cmds = [f'''CREATE TABLE IF NOT EXISTS {table_name}(
{key_name} INTEGER PRIMARY KEY,
{desc_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT,
{parent_id_field} INTEGER
)''',
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_new}=va', '{user_access.user_access_group_new}=va');"
]
select_comments_prefix = ''
table = bd_table.Table(table_name, [
bd_table.TableField(key_name, bd_table.TableFieldDestiny.KEY, bd_table.TableFieldType.INT),
bd_table.TableField(name_field, bd_table.TableFieldDestiny.NAME, bd_table.TableFieldType.STR),
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),
bd_table.TableField(parent_id_field, bd_table.TableFieldDestiny.PARENT_ID, bd_table.TableFieldType.INT),
])
init_access = f'{user_access.user_access_group_new}=va'
fsm = {
mod_table_operate.FSMs.CREATE: FSMCreateComment,
mod_table_operate.FSMs.EDIT_NAME: FSMEditCommentNameItem,
mod_table_operate.FSMs.EDIT_DESC: FSMEditCommentDescItem,
mod_table_operate.FSMs.EDIT_PHOTO: FSMEditCommentPhotoItem,
mod_table_operate.FSMs.EDIT_ACCESS: FSMEditCommentAccessItem,
}
# ---------------------------------------------------------
# Сообщения
comments_button_name = "⚏ Комментарии"
base_comment_message = f'''
<b>{comments_button_name}</b>
'''
list_comment_button_name = "📃 Список комментариев"
select_comment_message = '''
# Сообщения и кнопки
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: '''
Пожалуйста, выберите комментарий:
'''
error_find_proj_message = '''
''',
mod_table_operate.Messages.ERROR_FIND: '''
Ошибка, комментарий не найден
'''
comment_open_message = f'''
<b>Комментарий</b>
''',
mod_table_operate.Messages.OPEN: f'''
<b>Комментарий: #{name_field}</b>
#{desc_field}
Время создания: #{create_datetime_field}
'''
# Создание комментариев
add_comment_button_name = "☑ Добавить комментарий"
comment_create_desc_message = '''
Введите свой комментарий:
'''
comment_success_create_message = '''✅ Комментарий успешно добавлен!'''
# Редактирование комментариев.
edit_comment_button_name = "🛠 Редактировать комментарий"
comment_start_edit_message= '''
''',
mod_table_operate.Messages.CREATE_NAME: '''
Создание комментария. Шаг 1
Введите название комментария:
''',
mod_table_operate.Messages.CREATE_DESC: '''
Создание комментария. Шаг 2
Введите описание комментария:
''',
mod_table_operate.Messages.CREATE_PHOTO: '''
Создание комментария. Шаг 3
Загрузите обложку для комментария (Фото):
Она будет отображаться в его описании.
''',
mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Комментарий успешно добавлен!''',
mod_table_operate.Messages.START_EDIT: '''
Пожалуйста, выберите действие:
'''
comment_select_to_edit_message = '''
''',
mod_table_operate.Messages.SELECT_TO_EDIT: '''
Выберите комментарий, который вы хотите отредактировать.
'''
edit_comment_desc_button_name = "𝌴 Изменить комментарий"
comment_edit_desc_message = f'''
Текущий комментарий:
''',
mod_table_operate.Messages.EDIT_PHOTO: '''
Загрузите новую обложку для комментария (Фото):
Она будет отображаться в его описании.
''',
mod_table_operate.Messages.EDIT_NAME: f'''
Текущее название комментария:
#{name_field}
Введите новое название комментария:
''',
mod_table_operate.Messages.EDIT_DESC: f'''
Текущее описание комментария:
#{desc_field}
Введите отредактированный комментарий:
'''
edit_comment_access_button_name = "✋ Изменить доступ к комментарию"
comment_edit_access_message = f'''
Текущий доступ к комментарию:
Введите новое описание комментария:
''',
mod_table_operate.Messages.EDIT_ACCESS: f'''
Текущий доступ к комментарийу:
#{access_field}
{user_access.user_access_readme}
Введите новую строку доступа:
'''
comment_success_edit_message = '''✅ Комментарий успешно отредактирован!'''
# Удаление комментариев
del_comment_button_name = "❌ Удалить комментарий"
comment_select_to_delete_message = '''
Выберите комментарий, которую вы хотите удалить.
'''
comment_success_delete_message = '''✅ Комментарий успешно удалён!'''
# ---------------------------------------------------------
# Работа с кнопками
def GetEditCommentKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = GetModuleButtons() + [
keyboard.ButtonWithAccess(edit_comment_desc_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_comment_access_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetStartCommentKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(list_comment_button_name, user_access.AccessMode.VIEW, GetAccess()),
keyboard.ButtonWithAccess(add_comment_button_name, user_access.AccessMode.ADD, GetAccess()),
keyboard.ButtonWithAccess(del_comment_button_name, user_access.AccessMode.DELETE, GetAccess()),
keyboard.ButtonWithAccess(edit_comment_button_name, user_access.AccessMode.EDIT, GetAccess())
]
mods = [start, projects, tasks, needs]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
# ---------------------------------------------------------
# Обработка сообщений
# стартовое сообщение
async def CommentsOpen(a_Message : types.message, state = None):
return simple_message.WorkFuncResult(base_comment_message)
def GetButtonNameAndKeyValueAndAccess(a_Item):
# commentDesc commentID commentAccess
return a_Item[1], a_Item[0], a_Item[2]
def ShowMessageTemplate(a_StringMessage):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 4):
return simple_message.WorkFuncResult(error_find_proj_message)
msg = a_StringMessage.\
replace(f'#{desc_field}', a_Item[1]).\
replace(f'#{create_datetime_field}', a_Item[3]).\
replace(f'#{access_field}', a_Item[2])
return simple_message.WorkFuncResult(msg, item_access = a_Item[2])
return ShowMessage
def SimpleMessageTemplate(a_StringMessage):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
return simple_message.WorkFuncResult(a_StringMessage)
return ShowMessage
# Удаление комментариев
async def CommentPreDelete(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 4):
return simple_message.WorkFuncResult(error_find_proj_message)
access = a_Item[2]
return simple_message.WorkFuncResult('', None, item_access = access)
async def CommentPostDelete(a_CallbackQuery : types.CallbackQuery, a_ItemID):
log.Success(f'Комментарий №{a_ItemID} был удалён пользователем {a_CallbackQuery.from_user.id}.')
#TODO: удалить вложенные
return simple_message.WorkFuncResult(comment_success_delete_message)
# ---------------------------------------------------------
# Работа с базой данных комментариев
def AddBDItemFunc(a_ItemData, a_UserID):
print(a_ItemData)
res, error = bot_bd.SQLRequestToBD(f'INSERT INTO {table_name}({desc_field}, {access_field}, {parent_id_field}, {create_datetime_field}) VALUES(?, ?, ?, {bot_bd.GetBDDateTimeNow()})',
commit = True, return_error = True, param = (a_ItemData[desc_field], access.GetItemDefaultAccessForModule(module_name) + f";{a_UserID}=+", a_ItemData[parent_id_field]))
if error:
log.Error(f'Пользоватлель {a_UserID}. Ошибка добавления записи в таблицу {table_name} ({a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
else:
log.Success(f'Пользоватлель {a_UserID}. Добавлена запись в таблицу {table_name} ({a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
return res, error
# ---------------------------------------------------------
# API
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [keyboard.ButtonWithAccess(comments_button_name, user_access.AccessMode.VIEW, GetAccess())]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
defaul_keyboard_func = GetStartCommentKeyboardButtons
def RegisterSelectParent(a_ButtonName, access_mode):
a_PrefixBase = a_ButtonName
a_Prefix = bd_item_select.FirstSelectBDItemRegisterHandlers(dp, \
a_PrefixBase, \
a_ButtonName, \
projects.table_name, \
projects.key_name, \
projects.GetButtonNameAndKeyValueAndAccess, \
projects.select_project_message, \
projects.GetAccess, \
access_mode = access_mode\
)
a_Prefix = bd_item_select.NextSelectBDItemRegisterHandlers(dp, \
a_Prefix, \
tasks.parent_id_field, \
tasks.table_name, \
tasks.key_name, \
tasks.GetButtonNameAndKeyValueAndAccess, \
tasks.select_task_message, \
tasks.GetAccess, \
access_mode = access_mode\
)
a_Prefix = bd_item_select.NextSelectBDItemRegisterHandlers(dp, \
a_Prefix, \
needs.parent_id_field, \
needs.table_name, \
needs.key_name, \
needs.GetButtonNameAndKeyValueAndAccess, \
needs.select_need_message, \
needs.GetAccess, \
access_mode = access_mode\
)
return a_Prefix
# Стартовое сообщение
dp.register_message_handler(simple_message.SimpleMessageTemplate(CommentsOpen, defaul_keyboard_func, GetAccess), text = comments_button_name)
# Список комментариев
a_Prefix = RegisterSelectParent(list_comment_button_name, user_access.AccessMode.VIEW)
bd_item_view.LastSelectAndShowBDItemRegisterHandlers(dp, \
a_Prefix, parent_id_field, \
table_name, key_name, \
ShowMessageTemplate(comment_open_message), \
GetButtonNameAndKeyValueAndAccess, \
select_comment_message, \
GetAccess, \
defaul_keyboard_func, \
access_mode = user_access.AccessMode.VIEW\
)
global select_comments_prefix
select_comments_prefix = a_Prefix
# Удаление комментариев
a_Prefix = RegisterSelectParent(del_comment_button_name, user_access.AccessMode.DELETE)
bd_item_delete.DeleteBDItemRegisterHandlers(dp, \
a_Prefix, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
table_name, \
key_name, \
parent_id_field, \
CommentPreDelete, \
CommentPostDelete, \
GetButtonNameAndKeyValueAndAccess, \
select_comment_message, \
GetAccess, \
defaul_keyboard_func\
)
# Добавление комментариев
a_Prefix = RegisterSelectParent(add_comment_button_name, user_access.AccessMode.ADD)
bd_item_add.AddBDItem1RegisterHandlers(dp, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
FSMCreateComment, \
AddBDItemFunc, \
SimpleMessageTemplate(comment_create_desc_message), \
SimpleMessageTemplate(comment_success_create_message), \
a_Prefix,\
needs.table_name, \
needs.key_name, \
desc_field, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
GetStartCommentKeyboardButtons,\
bd_item.FieldType.text
)
def RegisterEdit(a_ButtonName, a_FSM, a_EditMessage, a_FieldName, a_FieldType, a_AccessMode = user_access.AccessMode.EDIT):
a_Prefix = RegisterSelectParent(a_ButtonName, a_AccessMode)
bd_item_edit.EditBDItemRegisterHandlers(dp, \
a_Prefix, \
a_FSM, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
comment_select_to_edit_message, \
ShowMessageTemplate(a_EditMessage), \
ShowMessageTemplate(comment_success_edit_message), \
table_name, \
key_name, \
parent_id_field, \
a_FieldName, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
edit_keyboard_func, \
access_mode = a_AccessMode, \
field_type = a_FieldType\
)
# Редактирование комментариев
edit_keyboard_func = GetEditCommentKeyboardButtons
dp.register_message_handler(simple_message.InfoMessageTemplate(comment_start_edit_message, edit_keyboard_func, GetAccess, access_mode = user_access.AccessMode.EDIT), text = edit_comment_button_name)
RegisterEdit(edit_comment_desc_button_name, FSMEditCommentDescItem, comment_edit_desc_message, desc_field, bd_item.FieldType.text)
RegisterEdit(edit_comment_access_button_name, FSMEditCommentAccessItem, comment_edit_access_message, access_field, bd_item.FieldType.text)
''',
mod_table_operate.Messages.SUCCESS_EDIT: '''✅ Комментарий успешно отредактирован!''',
mod_table_operate.Messages.SELECT_TO_DELETE: '''
Выберите комментарий, который вы хотите удалить.
''',
mod_table_operate.Messages.SUCCESS_DELETE: '''✅ Комментарий успешно удалён!''',
}
class ModuleComments(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

156
bot_modules/groups.py

@ -3,13 +3,12 @@
# Группы пользователей
from bot_sys import bot_bd, log, config, keyboard, user_access
from bot_modules import start, access
from template import simple_message, sql_request
from bot_sys import keyboard, user_access, bot_bd
from bot_modules import mod_simple_message
from template import simple_message, sql_request, bd_item
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.dispatcher import Dispatcher
class FSMRequestToBD(StatesGroup):
sqlRequest = State()
@ -27,34 +26,9 @@ user_id_field = 'user_id'
access_field = 'access'
create_datetime_field = 'createDateTime'
init_bd_cmds = [f"""CREATE TABLE IF NOT EXISTS {table_groups_name}(
{key_table_groups_name} INTEGER PRIMARY KEY NOT NULL,
{name_table_groups_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT,
UNIQUE({key_table_groups_name}),
UNIQUE({name_table_groups_field})
);""",
f"""CREATE TABLE IF NOT EXISTS {table_user_in_groups_name}(
{user_id_field} INTEGER,
{key_table_groups_name} INTEGER,
{access_field} TEXT,
{create_datetime_field} TEXT,
UNIQUE({user_id_field}, {key_table_groups_name})
);""",
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_new}=-', '{user_access.user_access_group_new}=-');",
f"INSERT OR IGNORE INTO {table_groups_name} ({name_table_groups_field}, {access_field}, {create_datetime_field}) VALUES ('{user_access.user_access_group_new}', '{user_access.user_access_group_new}=-', {bot_bd.GetBDDateTimeNow()});"
]
# ---------------------------------------------------------
# Сообщения
group_start_message = '''
<b>Группы пользователей находятся в стадии разработки</b>
Пока можете воспользоваться хардкорным способом через запросы к БД
'''
request_start_message = '''
**Задайте запрос к БД**
@ -73,58 +47,84 @@ help_message = '''
`user_in_groups(user_id, group_id)` - содержит соответсвия ID пользователей и групп
'''
user_group_button_name = "▦ Группы пользователей"
sql_request_button_name = "⛃ Запрос к БД для редактирования групп"
help_button_name = "📄 Информация по группам"
# ---------------------------------------------------------
# Работа с кнопками
def GetEditGroupKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(sql_request_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(help_button_name, user_access.AccessMode.VIEW, GetAccess())
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
button_names = {
mod_simple_message.ButtonNames.START: "▦ Группы пользователей",
}
# ---------------------------------------------------------
# Обработка сообщений
# ---------------------------------------------------------
# Работа с базой данных групп
def GetGroupIDForUser(a_UserID):
return bot_bd.SQLRequestToBD('SELECT group_id FROM user_in_groups WHERE user_id = ?', param = [a_UserID])
def GetGroupNamesForUser(a_UserID):
return bot_bd.SQLRequestToBD('SELECT groupName FROM user_groups WHERE group_id=(SELECT group_id FROM user_in_groups WHERE user_id = ?)', param = [a_UserID])
# ---------------------------------------------------------
# API
def GetUserGroupData(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)
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [keyboard.ButtonWithAccess(user_group_button_name, user_access.AccessMode.VIEW, GetAccess())]
messages = {
mod_simple_message.Messages.START: '''
<b>Группы пользователей находятся в стадии разработки</b>
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
dp.register_message_handler(simple_message.InfoMessageTemplate(group_start_message, GetEditGroupKeyboardButtons, GetAccess), text = user_group_button_name)
dp.register_message_handler(simple_message.InfoMessageTemplate(help_message, GetEditGroupKeyboardButtons, GetAccess), text = help_button_name)
Пока можете воспользоваться хардкорным способом через запросы к БД
''',
}
init_access = f'{user_access.user_access_group_new}=-'
class ModuleGroups(mod_simple_message.SimpleMessageModule):
def __init__(self, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log):
super().__init__(messages, button_names, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log)
self.m_SqlRequestButtonName = self.CreateButton('sql request', sql_request_button_name)
self.m_RequestStartMessage = self.CreateMessage('equest start', request_start_message)
self.m_HelpButtonName = self.CreateButton('help', help_button_name)
self.m_HelpMessage = self.CreateMessage('help', help_message)
self.m_HelpMessageHandler = simple_message.InfoMessageTemplate(
self.m_Bot,
self.m_HelpMessage,
self.m_GetStartKeyboardButtonsFunc,
None,
self.m_GetAccessFunc
)
def GetInitBDCommands(self):
return super(). GetInitBDCommands() + [
f"""CREATE TABLE IF NOT EXISTS {table_groups_name}(
{key_table_groups_name} INTEGER PRIMARY KEY NOT NULL,
{name_table_groups_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT,
UNIQUE({key_table_groups_name}),
UNIQUE({name_table_groups_field})
);""",
f"""CREATE TABLE IF NOT EXISTS {table_user_in_groups_name}(
{user_id_field} INTEGER,
{key_table_groups_name} INTEGER,
{access_field} TEXT,
{create_datetime_field} TEXT,
UNIQUE({user_id_field}, {key_table_groups_name})
);""",
f"INSERT OR IGNORE INTO {table_groups_name} ({name_table_groups_field}, {access_field}, {create_datetime_field}) VALUES ('{user_access.user_access_group_new}', '{user_access.user_access_group_new}=-', {bot_bd.GetBDDateTimeNow()});"
]
def GetName(self):
return module_name
def GetStartKeyboardButtons(self, a_Message, a_UserGroups):
mod_buttons = super().GetStartKeyboardButtons(a_Message, a_UserGroups)
cur_buttons = [
keyboard.ButtonWithAccess(self.m_SqlRequestButtonName, user_access.AccessMode.EDIT, self.GetAccess()),
keyboard.ButtonWithAccess(self.m_HelpButtonName , user_access.AccessMode.VIEW, self.GetAccess())
]
return mod_buttons + keyboard.MakeButtons(cur_buttons, a_UserGroups)
def RegisterHandlers(self):
super().RegisterHandlers()
sql_request.RequestToBDRegisterHandlers(
self.m_Bot,
self.m_SqlRequestButtonName,
self.m_RequestStartMessage,
FSMRequestToBD,
self.m_GetStartKeyboardButtonsFunc,
user_access.AccessMode.EDIT,
self.m_GetAccessFunc
)
self.m_Bot.RegisterMessageHandler(
self.m_HelpMessageHandler,
bd_item.GetCheckForTextFunc(self.m_HelpButtonName)
)
sql_request.RequestToBDRegisterHandlers(dp, sql_request_button_name, request_start_message, FSMRequestToBD, GetEditGroupKeyboardButtons, user_access.AccessMode.EDIT, GetAccess)

16
bot_modules/groups_utils.py

@ -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)

421
bot_modules/languages.py

@ -3,16 +3,12 @@
# Языки
from bot_sys import bot_bd, log, keyboard, user_access, user_messages
from bot_modules import start, access, groups, messages
from template import bd_item_view, simple_message, bd_item_delete, bd_item_edit, bd_item, bd_item_add
from aiogram import types
from bot_sys import bot_bd, keyboard, user_access, bd_table
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
from aiogram.dispatcher import Dispatcher
import sqlite3
class FSMCreateLanguage(StatesGroup):
name = State()
@ -25,7 +21,7 @@ class FSMEditLanguagePhotoItem(StatesGroup):
class FSMEditLanguageNameItem(StatesGroup):
item_field = State()
class FSMEditLanguageDeskItem(StatesGroup):
class FSMEditLanguageDescItem(StatesGroup):
item_field = State()
class FSMEditLanguageAccessItem(StatesGroup):
@ -42,336 +38,157 @@ photo_field = 'languagePhoto'
access_field = 'languageAccess'
create_datetime_field = 'languageCreateDateTime'
init_bd_cmds = [f'''CREATE TABLE IF NOT EXISTS {table_name}(
{key_name} INTEGER PRIMARY KEY,
{name_field} TEXT,
{desc_field} TEXT,
{photo_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT,
UNIQUE({key_name}),
UNIQUE({name_field})
)''',
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_all}=-', '{user_access.user_access_group_all}=-');"
]
# ---------------------------------------------------------
# Сообщения
table_name_field = bd_table.TableField(name_field, bd_table.TableFieldDestiny.NAME, bd_table.TableFieldType.STR)
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_name_field],
]
)
languages_button_name = "⚑ Языки"
base_language_message = f'''
<b>{languages_button_name}</b>
init_access = f'{user_access.user_access_group_all}=-'
'''
fsm = {
mod_table_operate.FSMs.CREATE: FSMCreateLanguage,
mod_table_operate.FSMs.EDIT_NAME: FSMEditLanguageNameItem,
mod_table_operate.FSMs.EDIT_DESC: FSMEditLanguageDescItem,
mod_table_operate.FSMs.EDIT_PHOTO: FSMEditLanguagePhotoItem,
mod_table_operate.FSMs.EDIT_ACCESS: FSMEditLanguageAccessItem,
}
list_language_button_name = "📃 Список языков"
select_language_message = '''
# ---------------------------------------------------------
# Сообщения и кнопки
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: '''
Пожалуйста, выберите язык:
'''
error_find_proj_message = '''
''',
mod_table_operate.Messages.ERROR_FIND: '''
Ошибка, язык не найден
'''
language_open_message = f'''
''',
mod_table_operate.Messages.OPEN: f'''
<b>Язык: #{name_field}</b>
#{desc_field}
Время создания: #{create_datetime_field}
'''
# Создание языка
add_language_button_name = "✅ Добавить язык"
language_create_name_message = '''
''',
mod_table_operate.Messages.CREATE_NAME: '''
Создание языка. Шаг 1
Введите название языка:
'''
language_create_desc_message = '''
''',
mod_table_operate.Messages.CREATE_DESC: '''
Создание языка. Шаг 2
Введите описание языка:
'''
language_create_photo_message = '''
''',
mod_table_operate.Messages.CREATE_PHOTO: '''
Создание языка. Шаг 3
Загрузите обложку для языка (Фото):
Она будет отображаться в его описании.
'''
language_success_create_message = '''✅ Язык успешно добавлен!'''
# Редактирование языка.
edit_language_button_name = "🛠 Редактировать язык"
language_start_edit_message= '''
''',
mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Язык успешно добавлен!''',
mod_table_operate.Messages.START_EDIT: '''
Пожалуйста, выберите действие:
'''
language_select_to_edit_message = '''
''',
mod_table_operate.Messages.SELECT_TO_EDIT: '''
Выберите язык, который вы хотите отредактировать.
'''
edit_language_photo_button_name = "☐ Изменить изображение в языке"
language_edit_photo_message = '''
''',
mod_table_operate.Messages.EDIT_PHOTO: '''
Загрузите новую обложку для языка (Фото):
Она будет отображаться в его описании.
'''
edit_language_name_button_name = "≂ Изменить название в языке"
language_edit_name_message = f'''
''',
mod_table_operate.Messages.EDIT_NAME: f'''
Текущее название языка:
#{name_field}
Введите новое название языка:
'''
edit_language_desc_button_name = "𝌴 Изменить описание в языке"
language_edit_desc_message = f'''
''',
mod_table_operate.Messages.EDIT_DESC: f'''
Текущее описание языка:
#{desc_field}
Введите новое описание языка:
'''
edit_language_access_button_name = "✋ Изменить доступ к языку"
language_edit_access_message = f'''
''',
mod_table_operate.Messages.EDIT_ACCESS: f'''
Текущий доступ к языку:
#{access_field}
{user_access.user_access_readme}
Введите новую строку доступа:
'''
language_success_edit_message = '''✅ Язык успешно отредактирован!'''
# Удаление языка
del_language_button_name = "❌ Удалить язык"
language_select_to_delete_message = '''
Выберите язык, которое вы хотите удалить.
'''
''',
mod_table_operate.Messages.SUCCESS_EDIT: '''✅ Язык успешно отредактирован!''',
mod_table_operate.Messages.SELECT_TO_DELETE: '''
Выберите язык, который вы хотите удалить.
Все задачи и потребности в этом языке так же будут удалены!
''',
mod_table_operate.Messages.SUCCESS_DELETE: '''✅ Язык успешно удалён!''',
}
class ModuleLanguages(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)
self.m_LanguageIDs = {}
def GetName(self):
return module_name
def GetLangID(self, a_Lang):
return self.m_LanguageIDs.get(a_Lang, None)
def GetLangName(self, a_LangID):
for lang_name, lang_id in self.m_LanguageIDs:
if a_LangID == lang_id:
return lang_name
return self.m_BotMessages.m_DefaultLanguage
def FlushLanguages(self):
msg = self.m_BotMessages.GetMessages()
for lang, msg_dict in msg.items():
self.AddOrIgnoreLang(lang)
langs = bd_item.GetAllItemsTemplate(self.m_Bot, table_name)()
if langs:
for l in langs:
self.m_LanguageIDs[l[1]] = str(l[0])
print('FlushLanguages', self.m_LanguageIDs)
def AddOrIgnoreLang(self, a_Lang : str):
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)
res, error = self.m_Bot.SQLRequest(f'INSERT OR IGNORE INTO {table_name}({photo_field}, {name_field}, {desc_field}, {access_field}, {create_datetime_field}) VALUES(?, ?, ?, ?, {bot_bd.GetBDDateTimeNow()})',
commit = True, return_error = True, param = (0, a_Lang, '', access_utils.GetItemDefaultAccessForModule(self.m_Bot, module_name)))
def OnChange(self):
self.FlushLanguages()
language_success_delete_message = '''✅ Язык успешно удален!'''
# ---------------------------------------------------------
# Работа с кнопками
def GetEditLanguageKeyboardButtons(a_Language, a_UserGroups):
cur_buttons = GetModuleButtons() + [
keyboard.ButtonWithAccess(edit_language_photo_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_language_name_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_language_desc_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_language_access_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetStartLanguageKeyboardButtons(a_Language, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(list_language_button_name, user_access.AccessMode.VIEW, GetAccess()),
keyboard.ButtonWithAccess(add_language_button_name, user_access.AccessMode.ADD, GetAccess()),
keyboard.ButtonWithAccess(del_language_button_name, user_access.AccessMode.DELETE, GetAccess()),
keyboard.ButtonWithAccess(edit_language_button_name, user_access.AccessMode.EDIT, GetAccess())
]
mods = [start, messages]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetViewItemInlineKeyboardTemplate(a_ItemID):
def GetViewItemInlineKeyboard(a_Message, a_UserGroups):
cur_buttons = [
keyboard.InlineButton(messages.list_message_button_name, messages.select_messages_prefix, a_ItemID, GetAccess(), user_access.AccessMode.VIEW),
]
return keyboard.MakeInlineKeyboard(cur_buttons, a_UserGroups)
return GetViewItemInlineKeyboard
# ---------------------------------------------------------
# Обработка языков
# стартовое язык
async def LanguagesOpen(a_Language : types.message, state = None):
return simple_message.WorkFuncResult(base_language_message)
def GetButtonNameAndKeyValueAndAccess(a_Item):
# languageName languageID languageAccess
return a_Item[1], a_Item[0], a_Item[4]
def ShowMessageTemplate(a_StringLanguage, keyboard_template_func = None):
async def ShowLanguage(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
msg = a_StringLanguage.\
replace(f'#{name_field}', a_Item[1]).\
replace(f'#{desc_field}', a_Item[2]).\
replace(f'#{create_datetime_field}', a_Item[5]).\
replace(f'#{access_field}', a_Item[4])
keyboard_func = None
if keyboard_template_func:
keyboard_func = keyboard_template_func(a_Item[0])
return simple_message.WorkFuncResult(msg, photo_id = a_Item[3], item_access = a_Item[4], keyboard_func = keyboard_func)
return ShowLanguage
def SimpleMessageTemplate(a_StringLanguage):
async def ShowLanguage(a_CallbackQuery : types.CallbackQuery, a_Item):
return simple_message.WorkFuncResult(a_StringLanguage)
return ShowLanguage
# Удаление языка
async def LanguagePreDelete(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
access = a_Item[4]
return simple_message.WorkFuncResult('', None, item_access = access)
async def LanguagePostDelete(a_CallbackQuery : types.CallbackQuery, a_ItemID):
log.Success(f'Язык №{a_ItemID} был удалён пользователем {a_CallbackQuery.from_user.id}.')
#TODO: удалить вложенные
FlushLanguages()
return simple_message.WorkFuncResult(language_success_delete_message)
# ---------------------------------------------------------
# Работа с базой данных языков
def AddBDItemFunc(a_ItemData, a_UserID):
res, error = bot_bd.SQLRequestToBD(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], access.GetItemDefaultAccessForModule(module_name) + f";{a_UserID}=+"))
if error:
log.Error(f'Пользоватлель {a_UserID}. Ошибка добавления записи в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
else:
log.Success(f'Пользоватлель {a_UserID}. Добавлена запись в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
FlushLanguages()
return res, error
# ---------------------------------------------------------
# API
def AddOrIgnoreLang(a_Lang : str):
res, error = bot_bd.SQLRequestToBD(f'INSERT OR IGNORE INTO {table_name}({photo_field}, {name_field}, {desc_field}, {access_field}, {create_datetime_field}) VALUES(?, ?, ?, ?, {bot_bd.GetBDDateTimeNow()})',
commit = True, return_error = True, param = (0, a_Lang, '', access.GetItemDefaultAccessForModule(module_name)))
g_languages = {}
def GetLangID(a_Lang):
global g_languages
return g_languages.get(a_Lang, None)
def GetLangName(a_LangID):
global g_languages
for lang_name, lang_id in g_languages:
if a_LangID == lang_id:
return lang_name
return user_messages.default_language
def FlushLanguages():
global g_languages
msg = user_messages.GetMessages()
for lang, msg_dict in msg.items():
AddOrIgnoreLang(lang)
langs = bd_item.GetAllItemsTemplate(table_name)()
if langs:
for l in langs:
g_languages[l[1]] = str(l[0])
print('FlushLanguages', g_languages)
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [
keyboard.ButtonWithAccess(languages_button_name, user_access.AccessMode.VIEW, GetAccess()),
]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
defaul_keyboard_func = GetStartLanguageKeyboardButtons
# Список языков
dp.register_message_handler(simple_message.SimpleMessageTemplate(LanguagesOpen, defaul_keyboard_func, GetAccess), text = languages_button_name)
bd_item_view.FirstSelectAndShowBDItemRegisterHandlers(dp, \
list_language_button_name, \
table_name, \
key_name, \
ShowMessageTemplate(language_open_message, GetViewItemInlineKeyboardTemplate), \
GetButtonNameAndKeyValueAndAccess, \
select_language_message, \
GetAccess, \
defaul_keyboard_func\
)
# Удаление языка
bd_item_delete.DeleteBDItemRegisterHandlers(dp, \
None, \
bd_item.GetCheckForTextFunc(del_language_button_name), \
table_name, \
key_name, \
None, \
LanguagePreDelete, \
LanguagePostDelete, \
GetButtonNameAndKeyValueAndAccess, \
select_language_message, \
GetAccess, \
defaul_keyboard_func\
)
# Добавление языка
bd_item_add.AddBDItem3RegisterHandlers(dp, \
bd_item.GetCheckForTextFunc(add_language_button_name), \
FSMCreateLanguage,\
FSMCreateLanguage.name,\
FSMCreateLanguage.desc, \
FSMCreateLanguage.photo,\
AddBDItemFunc, \
SimpleMessageTemplate(language_create_name_message), \
SimpleMessageTemplate(language_create_desc_message), \
SimpleMessageTemplate(language_create_photo_message), \
SimpleMessageTemplate(language_success_create_message), \
None,\
None, \
None, \
name_field, \
desc_field, \
photo_field, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
GetStartLanguageKeyboardButtons\
)
# Редактирование языка
edit_keyboard_func = GetEditLanguageKeyboardButtons
def RegisterEdit(a_ButtonName, a_FSM, a_EditLanguage, a_FieldName, a_FieldType, a_AccessMode = user_access.AccessMode.EDIT):
bd_item_edit.EditBDItemRegisterHandlers(dp, \
None, \
a_FSM, \
bd_item.GetCheckForTextFunc(a_ButtonName), \
language_select_to_edit_message, \
ShowMessageTemplate(a_EditLanguage), \
ShowMessageTemplate(language_success_edit_message), \
table_name, \
key_name, \
None, \
a_FieldName, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
edit_keyboard_func, \
access_mode = a_AccessMode, \
field_type = a_FieldType\
)
dp.register_message_handler(simple_message.InfoMessageTemplate(language_start_edit_message, edit_keyboard_func, GetAccess, access_mode = user_access.AccessMode.EDIT), text = edit_language_button_name)
RegisterEdit(edit_language_photo_button_name, FSMEditLanguagePhotoItem, language_edit_photo_message, photo_field, bd_item.FieldType.photo)
RegisterEdit(edit_language_name_button_name, FSMEditLanguageNameItem, language_edit_name_message, name_field, bd_item.FieldType.text)
RegisterEdit(edit_language_desc_button_name, FSMEditLanguageDeskItem, language_edit_desc_message, desc_field, bd_item.FieldType.text)
RegisterEdit(edit_language_access_button_name, FSMEditLanguageAccessItem, language_edit_access_message, access_field, bd_item.FieldType.text)

451
bot_modules/messages.py

@ -3,16 +3,12 @@
# Сообщения
from bot_sys import bot_bd, log, keyboard, user_access, user_messages
from bot_modules import start, access, groups, languages
from template import bd_item_view, simple_message, bd_item_delete, bd_item_edit, bd_item, bd_item_add, bd_item_select
from aiogram import types
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
from aiogram.dispatcher import Dispatcher
import sqlite3
class FSMCreateMessage(StatesGroup):
name = State()
@ -47,355 +43,158 @@ access_field = 'messageAccess'
create_datetime_field = 'messageCreateDateTime'
parent_id_field = 'languageID'
init_bd_cmds = [f'''CREATE TABLE IF NOT EXISTS {table_name}(
{key_name} INTEGER PRIMARY KEY,
{name_field} TEXT,
{desc_field} TEXT,
{photo_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT,
{parent_id_field} INTEGER,
UNIQUE({key_name}),
UNIQUE({name_field}, {parent_id_field})
)''',
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_all}=-', '{user_access.user_access_group_all}=-');"
]
select_messages_prefix = ''
# ---------------------------------------------------------
# Сообщения
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],
]
)
messages_button_name = "✉ Сообщения"
base_message_message = '''
<b> Сообщения</b>
init_access = f'{user_access.user_access_group_all}=-'
'''
fsm = {
mod_table_operate.FSMs.CREATE: FSMCreateMessage,
mod_table_operate.FSMs.EDIT_NAME: FSMEditMessageNameItem,
mod_table_operate.FSMs.EDIT_DESC: FSMEditMessageDescItem,
mod_table_operate.FSMs.EDIT_PHOTO: FSMEditMessagePhotoItem,
mod_table_operate.FSMs.EDIT_ACCESS: FSMEditMessageAccessItem,
}
list_message_button_name = "📃 Список сообщений"
select_message_message = '''
# ---------------------------------------------------------
# Сообщения и кнопки
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: '''
Пожалуйста, выберите сообщение:
'''
error_find_proj_message = '''
Ошибка, сообщенийа не найдена
'''
message_open_message = f'''
''',
mod_table_operate.Messages.ERROR_FIND: '''
Ошибка, сообщение не найден
''',
mod_table_operate.Messages.OPEN: f'''
<b>Сообщение: #{name_field}</b>
#{desc_field}
Время создания: #{create_datetime_field}
'''
# Создание сообщения
add_message_button_name = "☑ Добавить сообщение"
message_create_name_message = '''
''',
mod_table_operate.Messages.CREATE_NAME: '''
Создание сообщения. Шаг 1
Введите название сообщения:
'''
message_create_desc_message = '''
''',
mod_table_operate.Messages.CREATE_DESC: '''
Создание сообщения. Шаг 2
Введите описание сообщения:
'''
message_create_photo_message = '''
''',
mod_table_operate.Messages.CREATE_PHOTO: '''
Создание сообщения. Шаг 3
Загрузите обложку для сообщения (Фото):
Она будет отображаться в её описании.
'''
message_success_create_message = '''✅ Сообщение успешно добавлено!'''
# Редактирование сообщения.
edit_message_button_name = "🛠 Редактировать сообщение"
message_start_edit_message= '''
Она будет отображаться в его описании.
''',
mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Сообщение успешно добавлено!''',
mod_table_operate.Messages.START_EDIT: '''
Пожалуйста, выберите действие:
'''
message_select_to_edit_message = '''
Выберите сообщение, которую вы хотите отредактировать.
'''
edit_message_photo_button_name = "☐ Изменить изображение у сообщения"
message_edit_photo_message = '''
''',
mod_table_operate.Messages.SELECT_TO_EDIT: '''
Выберите сообщение, который вы хотите отредактировать.
''',
mod_table_operate.Messages.EDIT_PHOTO: '''
Загрузите новую обложку для сообщения (Фото):
Она будет отображаться в её описании.
'''
edit_message_name_button_name = "≂ Изменить название у сообщения"
message_edit_name_message = f'''
Она будет отображаться в его описании.
''',
mod_table_operate.Messages.EDIT_NAME: f'''
Текущее название сообщения:
#{name_field}
Введите новое название сообщения:
'''
edit_message_desc_button_name = "𝌴 Изменить описание у сообщения"
message_edit_desc_message = f'''
''',
mod_table_operate.Messages.EDIT_DESC: f'''
Текущее описание сообщения:
#{desc_field}
Введите новое описание сообщения:
'''
edit_message_access_button_name = "✋ Изменить доступ к сообщению"
message_edit_access_message = f'''
Текущий доступ к сообщению:
''',
mod_table_operate.Messages.EDIT_ACCESS: f'''
Текущий доступ к сообщениеу:
#{access_field}
{user_access.user_access_readme}
Введите новую строку доступа:
'''
message_success_edit_message = '''✅ Сообщение успешно отредактировано!'''
# Удаление сообщения
del_message_button_name = "❌ Удалить сообщение"
message_select_to_delete_message = '''
Выберите сообщение, которую вы хотите удалить.
'''
message_success_delete_message = '''✅ Сообщение успешно удалено!'''
# ---------------------------------------------------------
# Работа с кнопками
def GetEditMessageKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = GetModuleButtons() + [
keyboard.ButtonWithAccess(edit_message_photo_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_message_name_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_message_desc_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_message_access_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetStartMessageKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(list_message_button_name, user_access.AccessMode.VIEW, GetAccess()),
keyboard.ButtonWithAccess(add_message_button_name, user_access.AccessMode.ADD, GetAccess()),
keyboard.ButtonWithAccess(del_message_button_name, user_access.AccessMode.DELETE, GetAccess()),
keyboard.ButtonWithAccess(edit_message_button_name, user_access.AccessMode.EDIT, GetAccess())
]
mods = [start, languages]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetViewItemInlineKeyboardTemplate(a_ItemID):
def GetViewItemInlineKeyboard(a_Message, a_UserGroups):
cur_buttons = [
#keyboard.InlineButton(needs.list_need_button_name, needs.select_needs_prefix, a_ItemID, GetAccess(), user_access.AccessMode.VIEW),
]
return keyboard.MakeInlineKeyboard(cur_buttons, a_UserGroups)
return GetViewItemInlineKeyboard
# ---------------------------------------------------------
# Обработка сообщений
# стартовое сообщение
async def MessagesOpen(a_Message : types.message, state = None):
return simple_message.WorkFuncResult(base_message_message)
def GetButtonNameAndKeyValueAndAccess(a_Item):
# messageName messageID messageAccess
return a_Item[1], a_Item[0], a_Item[4]
def ShowMessageTemplate(a_StringMessage, keyboard_template_func = None):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
if message_success_edit_message == a_StringMessage:
FlushMessages()
# TODO FlushMessages происходит рано. Нужно после изменений
msg = a_StringMessage.\
replace(f'#{name_field}', a_Item[1]).\
replace(f'#{desc_field}', a_Item[2]).\
replace(f'#{create_datetime_field}', a_Item[5]).\
replace(f'#{access_field}', a_Item[4])
keyboard_func = None
if keyboard_template_func:
keyboard_func = keyboard_template_func(a_Item[0])
return simple_message.WorkFuncResult(msg, photo_id = a_Item[3], item_access = a_Item[4], keyboard_func = keyboard_func)
return ShowMessage
def SimpleMessageTemplate(a_StringMessage):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
return simple_message.WorkFuncResult(a_StringMessage)
return ShowMessage
# Удаление сообщения
async def MessagePreDelete(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
access = a_Item[4]
return simple_message.WorkFuncResult('', None, item_access = access)
async def MessagePostDelete(a_CallbackQuery : types.CallbackQuery, a_ItemID):
log.Success(f'Сообщение №{a_ItemID} была удалена пользователем {a_CallbackQuery.from_user.id}.')
#TODO: удалить вложенные
FlushMessages()
return simple_message.WorkFuncResult(message_success_delete_message)
# ---------------------------------------------------------
# Работа с базой данных сообщений
def AddBDItemFunc(a_ItemData, a_UserID):
res, error = bot_bd.SQLRequestToBD(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], access.GetItemDefaultAccessForModule(module_name) + f";{a_UserID}=+", a_ItemData[parent_id_field]))
if error:
log.Error(f'Пользоватлель {a_UserID}. Ошибка добавления записи в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
else:
log.Success(f'Пользоватлель {a_UserID}. Добавлена запись в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
FlushMessages()
return res, error
# ---------------------------------------------------------
# API
def AddOrIgnoreMessage(a_Message : user_messages.Message):
return bot_bd.SQLRequestToBD(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.GetItemDefaultAccessForModule(module_name), languages.GetLangID(a_Message.m_Language)))
def FlushMessages():
msg = user_messages.GetMessages()
for lang, msg_dict in msg.items():
for msg_name, message in msg_dict.items():
AddOrIgnoreMessage(message)
msgs_bd = bd_item.GetAllItemsTemplate(table_name)()
if msgs_bd:
for m in msgs_bd:
name = m[1]
lang_id = m[6]
lang_name = languages.GetLangName(lang_id)
new_msg = user_messages.Message(name, m[2], lang_name, m[3], log.GetTimeNow())
if not msg.get(lang_name, None):
msg[lang_name] = {}
msg[lang_name][name] = new_msg
user_messages.UpdateSignal(log.GetTimeNow())
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [keyboard.ButtonWithAccess(messages_button_name, user_access.AccessMode.VIEW, GetAccess())]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
defaul_keyboard_func = GetStartMessageKeyboardButtons
def RegisterSelectParent(a_ButtonName, access_mode):
a_PrefixBase = a_ButtonName
return bd_item_select.FirstSelectBDItemRegisterHandlers(dp, \
a_PrefixBase, \
a_ButtonName, \
languages.table_name, \
languages.key_name, \
languages.GetButtonNameAndKeyValueAndAccess, \
languages.select_language_message, \
languages.GetAccess, access_mode = access_mode\
)
# Стартовое сообщение
dp.register_message_handler(simple_message.SimpleMessageTemplate(MessagesOpen, defaul_keyboard_func, GetAccess), text = messages_button_name)
# Список сообщений
a_Prefix = RegisterSelectParent(list_message_button_name, user_access.AccessMode.VIEW)
bd_item_view.LastSelectAndShowBDItemRegisterHandlers(dp, \
a_Prefix, parent_id_field, \
table_name, key_name, \
ShowMessageTemplate(message_open_message), \
GetButtonNameAndKeyValueAndAccess, \
select_message_message, \
GetAccess, \
defaul_keyboard_func, \
access_mode = user_access.AccessMode.VIEW\
)
global select_messages_prefix
select_messages_prefix = a_Prefix
# Удаление сообщения
a_Prefix = RegisterSelectParent(del_message_button_name, user_access.AccessMode.DELETE)
bd_item_delete.DeleteBDItemRegisterHandlers(dp, \
a_Prefix, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
table_name, \
key_name, \
parent_id_field, \
MessagePreDelete, \
MessagePostDelete, \
GetButtonNameAndKeyValueAndAccess, \
select_message_message, \
GetAccess, \
defaul_keyboard_func\
)
# Добавление сообщения
a_Prefix = RegisterSelectParent(add_message_button_name, user_access.AccessMode.ADD)
bd_item_add.AddBDItem3RegisterHandlers(dp, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
FSMCreateMessage, \
FSMCreateMessage.name,\
FSMCreateMessage.desc, \
FSMCreateMessage.photo,\
AddBDItemFunc, \
SimpleMessageTemplate(message_create_name_message), \
SimpleMessageTemplate(message_create_desc_message), \
SimpleMessageTemplate(message_create_photo_message), \
SimpleMessageTemplate(message_success_create_message), \
a_Prefix,\
languages.table_name, \
languages.key_name, \
name_field, \
desc_field, \
photo_field, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
GetStartMessageKeyboardButtons\
)
def RegisterEdit(a_ButtonName, a_FSM, a_EditMessage, a_FieldName, a_FieldType, a_AccessMode = user_access.AccessMode.EDIT):
a_Prefix = RegisterSelectParent(a_ButtonName, a_AccessMode)
bd_item_edit.EditBDItemRegisterHandlers(dp, \
a_Prefix, \
a_FSM, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
message_select_to_edit_message, \
ShowMessageTemplate(a_EditMessage), \
ShowMessageTemplate(message_success_edit_message), \
table_name, \
key_name, \
parent_id_field, \
a_FieldName, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
edit_keyboard_func, \
access_mode = a_AccessMode, \
field_type = a_FieldType\
)
# Редактирование сообщения
edit_keyboard_func = GetEditMessageKeyboardButtons
dp.register_message_handler(simple_message.InfoMessageTemplate(message_start_edit_message, edit_keyboard_func, GetAccess, access_mode = user_access.AccessMode.EDIT), text = edit_message_button_name)
RegisterEdit(edit_message_photo_button_name, FSMEditMessagePhotoItem, message_edit_photo_message, photo_field, bd_item.FieldType.photo)
RegisterEdit(edit_message_name_button_name, FSMEditMessageNameItem, message_edit_name_message, name_field, bd_item.FieldType.text)
RegisterEdit(edit_message_desc_button_name, FSMEditMessageDescItem, message_edit_desc_message, desc_field, bd_item.FieldType.text)
RegisterEdit(edit_message_access_button_name, FSMEditMessageAccessItem, message_edit_access_message, access_field, bd_item.FieldType.text)
''',
mod_table_operate.Messages.SUCCESS_EDIT: '''✅ Сообщение успешно отредактировано!''',
mod_table_operate.Messages.SELECT_TO_DELETE: '''
Выберите сообщение, который вы хотите удалить.
''',
mod_table_operate.Messages.SUCCESS_DELETE: '''✅ Сообщение успешно удалено!''',
}
class ModuleMessages(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_BotMessages.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_BotMessages.CreateMessage(name, desc, self.m_Log.GetTimeNow(), a_MessagePhotoID = photo_id, a_MessageLang = lang_name)
self.m_BotMessages.UpdateSignal(self.m_Log.GetTimeNow())
def OnChange(self):
self.FlushMessages()

15
bot_modules/mod_agregator.py

@ -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()

25
bot_modules/mod_interface.py

@ -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

112
bot_modules/mod_simple_message.py

@ -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))
)

386
bot_modules/mod_table_operate.py

@ -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

384
bot_modules/needs.py

@ -3,16 +3,11 @@
# Потребности
from bot_sys import bot_bd, log, keyboard, user_access
from bot_modules import start, access, groups, projects, tasks, comments
from template import bd_item_view, simple_message, bd_item_delete, bd_item_edit, bd_item, bd_item_add, bd_item_select
from aiogram import types
from bot_sys import bot_bd, keyboard, user_access, bd_table
from bot_modules import mod_table_operate, mod_simple_message
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.dispatcher import Dispatcher
import sqlite3
class FSMCreateNeed(StatesGroup):
name = State()
@ -20,19 +15,15 @@ class FSMCreateNeed(StatesGroup):
photo = State()
class FSMEditNeedPhotoItem(StatesGroup):
item_id = State()
item_field = State()
class FSMEditNeedNameItem(StatesGroup):
item_id = State()
item_field = State()
class FSMEditNeedDescItem(StatesGroup):
item_id = State()
item_field = State()
class FSMEditNeedAccessItem(StatesGroup):
item_id = State()
item_field = State()
# ---------------------------------------------------------
# БД
@ -47,340 +38,117 @@ access_field = 'needAccess'
create_datetime_field = 'needCreateDateTime'
parent_id_field = 'taskID'
init_bd_cmds = [f'''CREATE TABLE IF NOT EXISTS {table_name}(
{key_name} INTEGER PRIMARY KEY,
{name_field} TEXT,
{desc_field} TEXT,
{photo_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT,
{parent_id_field} INTEGER
)''',
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_new}=va', '{user_access.user_access_group_new}=va');"
]
select_needs_prefix = ''
table = bd_table.Table(table_name, [
bd_table.TableField(key_name, bd_table.TableFieldDestiny.KEY, bd_table.TableFieldType.INT),
bd_table.TableField(name_field, bd_table.TableFieldDestiny.NAME, bd_table.TableFieldType.STR),
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),
bd_table.TableField(parent_id_field, bd_table.TableFieldDestiny.PARENT_ID, bd_table.TableFieldType.INT),
])
init_access = f'{user_access.user_access_group_new}=va'
fsm = {
mod_table_operate.FSMs.CREATE: FSMCreateNeed,
mod_table_operate.FSMs.EDIT_NAME: FSMEditNeedNameItem,
mod_table_operate.FSMs.EDIT_DESC: FSMEditNeedDescItem,
mod_table_operate.FSMs.EDIT_PHOTO: FSMEditNeedPhotoItem,
mod_table_operate.FSMs.EDIT_ACCESS: FSMEditNeedAccessItem,
}
# ---------------------------------------------------------
# Сообщения
needs_button_name = "👉 Потребности"
base_need_message = f'''
<b>{needs_button_name}</b>
'''
list_need_button_name = "📃 Список потребностей"
select_need_message = '''
# Сообщения и кнопки
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: '''
Пожалуйста, выберите потребность:
'''
error_find_proj_message = '''
''',
mod_table_operate.Messages.ERROR_FIND: '''
Ошибка, потребность не найдена
'''
need_open_message = f'''
''',
mod_table_operate.Messages.OPEN: f'''
<b>Потребность: #{name_field}</b>
#{desc_field}
Время создания: #{create_datetime_field}
'''
# Создание потребностей
add_need_button_name = "☑ Добавить потребность"
need_create_name_message = '''
''',
mod_table_operate.Messages.CREATE_NAME: '''
Создание потребности. Шаг 1
Введите название потребности:
'''
need_create_desc_message = '''
''',
mod_table_operate.Messages.CREATE_DESC: '''
Создание потребности. Шаг 2
Введите описание потребности:
'''
need_create_photo_message = '''
''',
mod_table_operate.Messages.CREATE_PHOTO: '''
Создание потребности. Шаг 3
Загрузите обложку для потребности (Фото):
Она будет отображаться в её описании.
'''
need_success_create_message = '''✅ Потребность успешно добавлена!'''
# Редактирование потребностей.
edit_need_button_name = "🛠 Редактировать потребность"
need_start_edit_message= '''
''',
mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Потребность успешно добавлена!''',
mod_table_operate.Messages.START_EDIT: '''
Пожалуйста, выберите действие:
'''
need_select_to_edit_message = '''
''',
mod_table_operate.Messages.SELECT_TO_EDIT: '''
Выберите потребность, которую вы хотите отредактировать.
'''
edit_need_photo_button_name = "☐ Изменить изображение у потребности"
need_edit_photo_message = '''
''',
mod_table_operate.Messages.EDIT_PHOTO: '''
Загрузите новую обложку для потребности (Фото):
Она будет отображаться в её описании.
'''
edit_need_name_button_name = "≂ Изменить название у потребности"
need_edit_name_message = f'''
''',
mod_table_operate.Messages.EDIT_NAME: f'''
Текущее название потребности:
#{name_field}
Введите новое название потребности:
'''
edit_need_desc_button_name = "𝌴 Изменить описание у потребности"
need_edit_desc_message = f'''
''',
mod_table_operate.Messages.EDIT_DESC: f'''
Текущее описание потребности:
#{desc_field}
Введите новое описание потребности:
'''
edit_need_access_button_name = "✋ Изменить доступ к потребности"
need_edit_access_message = f'''
''',
mod_table_operate.Messages.EDIT_ACCESS: f'''
Текущий доступ к потребности:
#{access_field}
{user_access.user_access_readme}
Введите новую строку доступа:
'''
need_success_edit_message = '''✅ Потребность успешно отредактирована!'''
# Удаление потребностей
del_need_button_name = "❌ Удалить потребность"
need_select_to_delete_message = '''
''',
mod_table_operate.Messages.SUCCESS_EDIT: '''✅ Потребность успешно отредактирован!''',
mod_table_operate.Messages.SELECT_TO_DELETE: '''
Выберите потребность, которую вы хотите удалить.
Все сообщения в этой потребности так же будут удалены!
'''
need_success_delete_message = '''✅ Потребность успешно удалена!'''
# ---------------------------------------------------------
# Работа с кнопками
def GetEditNeedKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = GetModuleButtons() + [
keyboard.ButtonWithAccess(edit_need_photo_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_need_name_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_need_desc_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_need_access_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetStartNeedKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(list_need_button_name, user_access.AccessMode.VIEW, GetAccess()),
keyboard.ButtonWithAccess(add_need_button_name, user_access.AccessMode.ADD, GetAccess()),
keyboard.ButtonWithAccess(del_need_button_name, user_access.AccessMode.DELETE, GetAccess()),
keyboard.ButtonWithAccess(edit_need_button_name, user_access.AccessMode.EDIT, GetAccess())
]
mods = [start, projects, tasks, comments]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetViewItemInlineKeyboardTemplate(a_ItemID):
def GetViewItemInlineKeyboard(a_Message, a_UserGroups):
cur_buttons = [
keyboard.InlineButton(comments.list_comment_button_name, comments.select_comments_prefix, a_ItemID, GetAccess(), user_access.AccessMode.VIEW),
]
return keyboard.MakeInlineKeyboard(cur_buttons, a_UserGroups)
return GetViewItemInlineKeyboard
# ---------------------------------------------------------
# Обработка сообщений
# стартовое сообщение
async def NeedsOpen(a_Message : types.message, state = None):
return simple_message.WorkFuncResult(base_need_message)
def GetButtonNameAndKeyValueAndAccess(a_Item):
# needName needID needAccess
return a_Item[1], a_Item[0], a_Item[4]
def ShowMessageTemplate(a_StringMessage, keyboard_template_func = None):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
msg = a_StringMessage.\
replace(f'#{name_field}', a_Item[1]).\
replace(f'#{desc_field}', a_Item[2]).\
replace(f'#{create_datetime_field}', a_Item[5]).\
replace(f'#{access_field}', a_Item[4])
keyboard_func = None
if keyboard_template_func:
keyboard_func = keyboard_template_func(a_Item[0])
return simple_message.WorkFuncResult(msg, photo_id = a_Item[3], item_access = a_Item[4], keyboard_func = keyboard_func)
return ShowMessage
def SimpleMessageTemplate(a_StringMessage):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
return simple_message.WorkFuncResult(a_StringMessage)
return ShowMessage
# Удаление потребностей
async def NeedPreDelete(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
access = a_Item[4]
return simple_message.WorkFuncResult('', None, item_access = access)
async def NeedPostDelete(a_CallbackQuery : types.CallbackQuery, a_ItemID):
log.Success(f'Потребность №{a_ItemID} была удалена пользователем {a_CallbackQuery.from_user.id}.')
#TODO: удалить вложенные
return simple_message.WorkFuncResult(need_success_delete_message)
# ---------------------------------------------------------
# Работа с базой данных потребностей
def AddBDItemFunc(a_ItemData, a_UserID):
print(a_ItemData)
res, error = bot_bd.SQLRequestToBD(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], access.GetItemDefaultAccessForModule(module_name) + f";{a_UserID}=+", a_ItemData[parent_id_field]))
if error:
log.Error(f'Пользоватлель {a_UserID}. Ошибка добавления записи в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
else:
log.Success(f'Пользоватлель {a_UserID}. Добавлена запись в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
return res, error
# ---------------------------------------------------------
# API
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [keyboard.ButtonWithAccess(needs_button_name, user_access.AccessMode.VIEW, GetAccess())]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
defaul_keyboard_func = GetStartNeedKeyboardButtons
def RegisterSelectParent(a_ButtonName, access_mode):
a_PrefixBase = a_ButtonName
a_Prefix = bd_item_select.FirstSelectBDItemRegisterHandlers(dp, \
a_PrefixBase, \
a_ButtonName, \
projects.table_name, \
projects.key_name, \
projects.GetButtonNameAndKeyValueAndAccess, \
projects.select_project_message, \
projects.GetAccess, \
access_mode = access_mode\
)
a_Prefix = bd_item_select.NextSelectBDItemRegisterHandlers(dp, \
a_Prefix, \
tasks.parent_id_field, \
tasks.table_name, \
tasks.key_name, \
tasks.GetButtonNameAndKeyValueAndAccess, \
tasks.select_task_message, \
tasks.GetAccess, \
access_mode = access_mode\
)
return a_Prefix
# Стартовое сообщение
dp.register_message_handler(simple_message.SimpleMessageTemplate(NeedsOpen, defaul_keyboard_func, GetAccess), text = needs_button_name)
# Список потребностей
a_Prefix = RegisterSelectParent(list_need_button_name, user_access.AccessMode.VIEW)
bd_item_view.LastSelectAndShowBDItemRegisterHandlers(dp, \
a_Prefix, parent_id_field, \
table_name, key_name, \
ShowMessageTemplate(need_open_message, GetViewItemInlineKeyboardTemplate), \
GetButtonNameAndKeyValueAndAccess, \
select_need_message, \
GetAccess, \
defaul_keyboard_func, \
access_mode = user_access.AccessMode.VIEW\
)
global select_needs_prefix
select_needs_prefix = a_Prefix
# Удаление потребностей
a_Prefix = RegisterSelectParent(del_need_button_name, user_access.AccessMode.DELETE)
bd_item_delete.DeleteBDItemRegisterHandlers(dp, \
a_Prefix, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
table_name, \
key_name, \
parent_id_field, \
NeedPreDelete, \
NeedPostDelete, \
GetButtonNameAndKeyValueAndAccess, \
select_need_message, \
GetAccess, \
defaul_keyboard_func\
)
# Добавление потребностей
a_Prefix = RegisterSelectParent(add_need_button_name, user_access.AccessMode.ADD)
bd_item_add.AddBDItem3RegisterHandlers(dp, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
FSMCreateNeed, \
FSMCreateNeed.name,\
FSMCreateNeed.desc, \
FSMCreateNeed.photo,\
AddBDItemFunc, \
SimpleMessageTemplate(need_create_name_message), \
SimpleMessageTemplate(need_create_desc_message), \
SimpleMessageTemplate(need_create_photo_message), \
SimpleMessageTemplate(need_success_create_message), \
a_Prefix,\
tasks.table_name, \
tasks.key_name, \
name_field, \
desc_field, \
photo_field, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
GetStartNeedKeyboardButtons\
)
def RegisterEdit(a_ButtonName, a_FSM, a_EditMessage, a_FieldName, a_FieldType, a_AccessMode = user_access.AccessMode.EDIT):
a_Prefix = RegisterSelectParent(a_ButtonName, a_AccessMode)
bd_item_edit.EditBDItemRegisterHandlers(dp, \
a_Prefix, \
a_FSM, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
need_select_to_edit_message, \
ShowMessageTemplate(a_EditMessage), \
ShowMessageTemplate(need_success_edit_message), \
table_name, \
key_name, \
parent_id_field, \
a_FieldName, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
edit_keyboard_func, \
access_mode = a_AccessMode, \
field_type = a_FieldType\
)
Все комментарии в этой потребности так же будут удалены!
''',
mod_table_operate.Messages.SUCCESS_DELETE: '''✅ Потребность успешно удалёна!''',
}
# Редактирование потребностей
edit_keyboard_func = GetEditNeedKeyboardButtons
dp.register_message_handler(simple_message.InfoMessageTemplate(need_start_edit_message, edit_keyboard_func, GetAccess, access_mode = user_access.AccessMode.EDIT), text = edit_need_button_name)
class ModuleNeeds(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)
RegisterEdit(edit_need_photo_button_name, FSMEditNeedPhotoItem, need_edit_photo_message, photo_field, bd_item.FieldType.photo)
RegisterEdit(edit_need_name_button_name, FSMEditNeedNameItem, need_edit_name_message, name_field, bd_item.FieldType.text)
RegisterEdit(edit_need_desc_button_name, FSMEditNeedDescItem, need_edit_desc_message, desc_field, bd_item.FieldType.text)
RegisterEdit(edit_need_access_button_name, FSMEditNeedAccessItem, need_edit_access_message, access_field, bd_item.FieldType.text)
def GetName(self):
return module_name

136
bot_modules/profile.py

@ -3,12 +3,9 @@
# Профиль пользователя
from bot_sys import bot_bd, log, config, keyboard, user_access, user_messages
from bot_modules import start, access, groups
from template import simple_message
from aiogram import types
from aiogram.dispatcher import Dispatcher
from bot_sys import user_access, bot_bd, bd_table
from bot_modules import mod_simple_message, groups, access, access_utils, groups_utils
from template import bd_item, simple_message
# ---------------------------------------------------------
# БД
@ -24,30 +21,23 @@ language_code_field = 'userLanguageCode'
access_field = 'userAccess'
create_datetime_field = 'createDateTime'
init_bd_cmds = [f"""CREATE TABLE IF NOT EXISTS {table_name}(
{key_name} INTEGER,
{name_field} TEXT,
{name1_field} TEXT,
{name2_field} TEXT,
{is_bot_field} TEXT,
{language_code_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT,
UNIQUE({key_name})
);""",
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_new}=+', '{user_access.user_access_group_new}=+');"
]
def MSG(a_MessageName, a_MessageDesc):
def UpdateMSG(a_Message : user_messages.Message):
print(a_Message.m_MessageName, a_Message.m_MessageDesc)
globals()[a_Message.m_MessageName] = a_Message
user_messages.MSG(a_MessageName, a_MessageDesc, UpdateMSG, log.GetTimeNow())
# ---------------------------------------------------------
# Сообщения
MSG('profile_message', f'''
table = bd_table.Table(table_name, [
bd_table.TableField(key_name, bd_table.TableFieldDestiny.KEY, bd_table.TableFieldType.INT),
bd_table.TableField(name_field, bd_table.TableFieldDestiny.NAME, bd_table.TableFieldType.STR),
bd_table.TableField(name1_field, bd_table.TableFieldDestiny.DESC, bd_table.TableFieldType.STR),
bd_table.TableField(name2_field, bd_table.TableFieldDestiny.DESC, bd_table.TableFieldType.STR),
bd_table.TableField(is_bot_field, bd_table.TableFieldDestiny.DESC, bd_table.TableFieldType.STR),
bd_table.TableField(language_code_field, bd_table.TableFieldDestiny.DESC, 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),
])
button_names = {
mod_simple_message.ButtonNames.START: "📰 Профиль",
}
messages = {
mod_simple_message.Messages.START: f'''
<b>📰 Профиль:</b>
<b>ID:</b> #{key_name}
@ -56,73 +46,53 @@ MSG('profile_message', f'''
<b>Имя2:</b> #{name2_field}
<b>Код языка:</b> #{language_code_field}
<b>Дата добавления:</b> #{create_datetime_field}
''')
''',
}
user_profile_button_name = "📰 Профиль"
init_access = f'{user_access.user_access_group_new}=+'
# ---------------------------------------------------------
# Работа с кнопками
class ModuleProfile(mod_simple_message.SimpleMessageModule):
def __init__(self, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log):
super().__init__(messages, button_names, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log)
def GetStartKeyboardButtons(a_Message, a_UserGroups):
mods = [start]
return keyboard.MakeKeyboardForMods(mods, a_UserGroups)
def GetInitBDCommands(self):
return super(). GetInitBDCommands() + [
table.GetInitTableRequest(),
]
def GetName(self):
return module_name
# Основной обработчик главного сообщения
async def StartMessageHandler(self, a_Message, state = None):
user_info = GetUserInfo(self.m_Bot, a_Message.from_user.id)
lang = str(a_Message.from_user.language_code)
if not user_info is None:
msg = self.GetMessage(mod_simple_message.Messages.START)
msg = msg.GetMessageForLang(lang).StaticCopy()
msg.UpdateDesc(table.ReplaceAllFieldTags(msg.GetDesc(), user_info))
return simple_message.WorkFuncResult(msg, item_access = str(user_info[table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS)]))
return await super().StartMessageHandler(a_Message, state)
# ---------------------------------------------------------
# Обработка сообщений
async def ProfileOpen(a_Message, state = None):
user_info = GetUserInfo(a_Message.from_user.id)
msg = profile_message
if not user_info is None:
msg = str(msg).\
replace(f'#{key_name}', str(user_info[0])).\
replace(f'#{name_field}', str(user_info[1])).\
replace(f'#{name1_field}', str(user_info[2])).\
replace(f'#{name2_field}', str(user_info[3])).\
replace(f'#{is_bot_field}', str(user_info[4])).\
replace(f'#{language_code_field}', str(user_info[5])).\
replace(f'#{access_field}', str(user_info[6])).\
replace(f'#{create_datetime_field}', str(user_info[7]))
return simple_message.WorkFuncResult(msg, item_access = str(user_info[6]))
return simple_message.WorkFuncResult(msg)
# ---------------------------------------------------------
# Работа с базой данных пользователей
# Добавление пользователя, если он уже есть, то игнорируем
def AddUser(a_UserID, a_UserName, a_UserName1, a_UserName2, a_UserIsBot, a_LanguageCode):
bot_bd.SQLRequestToBD(f"INSERT OR IGNORE INTO users ({key_name}, {name_field}, {name1_field}, {name2_field}, {is_bot_field}, {language_code_field}, {access_field}, {create_datetime_field}) VALUES (?, ?, ?, ?, ?, ?, ?, {bot_bd.GetBDDateTimeNow()});",
commit=True, param = (a_UserID, a_UserName, a_UserName1, a_UserName2, a_UserIsBot, a_LanguageCode, access.GetItemDefaultAccessForModule(module_name)))
def AddUser(a_Bot, a_UserID, a_UserName, a_UserName1, a_UserName2, a_UserIsBot, a_LanguageCode):
a_Bot.SQLRequest(f"INSERT OR IGNORE INTO users ({key_name}, {name_field}, {name1_field}, {name2_field}, {is_bot_field}, {language_code_field}, {access_field}, {create_datetime_field}) VALUES (?, ?, ?, ?, ?, ?, ?, {bot_bd.GetBDDateTimeNow()});",
commit=True, param = (a_UserID, a_UserName, a_UserName1, a_UserName2, a_UserIsBot, a_LanguageCode, access_utils.GetItemDefaultAccessForModule(a_Bot, module_name)))
user_groups = groups.GetUserGroupData(a_UserID)
user_groups = groups_utils.GetUserGroupData(a_Bot, a_UserID)
# Если пользователь не состоит ни в одной группе, то добавляем его в группу user_access.user_access_group_new
if len(user_groups.group_names_list) == 0:
new_group_id = bot_bd.SQLRequestToBD(f'SELECT {groups.key_table_groups_name} FROM {groups.table_groups_name} WHERE {groups.name_table_groups_field} = ?',
new_group_id = a_Bot.SQLRequest(f'SELECT {groups.key_table_groups_name} FROM {groups.table_groups_name} WHERE {groups.name_table_groups_field} = ?',
param = [user_access.user_access_group_new])
if new_group_id and new_group_id[0]:
bot_bd.SQLRequestToBD(f"INSERT OR IGNORE INTO {groups.table_user_in_groups_name} ({groups.user_id_field}, {groups.key_table_groups_name}, {groups.access_field}, {groups.create_datetime_field}) VALUES (?, ?, ?, {bot_bd.GetBDDateTimeNow()});",
commit=True, param = (a_UserID, new_group_id[0][0], access.GetItemDefaultAccessForModule(module_name)))
a_Bot.SQLRequest(f"INSERT OR IGNORE INTO {groups.table_user_in_groups_name} ({groups.user_id_field}, {groups.key_table_groups_name}, {groups.access_field}, {groups.create_datetime_field}) VALUES (?, ?, ?, {bot_bd.GetBDDateTimeNow()});",
commit=True, param = (a_UserID, new_group_id[0][0], access_utils.GetItemDefaultAccessForModule(a_Bot, module_name)))
def GetUserInfo(a_UserID):
user_info = bot_bd.SQLRequestToBD('SELECT * FROM users WHERE user_id = ?', param = [a_UserID])
def GetUserInfo(a_Bot, a_UserID):
user_info = a_Bot.SQLRequest('SELECT * FROM users WHERE user_id = ?', param = [a_UserID])
if len(user_info) != 0:
return user_info[0]
return None
# ---------------------------------------------------------
# API
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [keyboard.ButtonWithAccess(user_profile_button_name, user_access.AccessMode.VIEW, GetAccess())]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
dp.register_message_handler(simple_message.SimpleMessageTemplate(ProfileOpen, GetStartKeyboardButtons, GetAccess), text = user_profile_button_name)

352
bot_modules/projects.py

@ -3,16 +3,11 @@
# Проекты
from bot_sys import bot_bd, log, keyboard, user_access, user_messages
from bot_modules import start, access, groups, tasks, needs, comments
from template import bd_item_view, simple_message, bd_item_delete, bd_item_edit, bd_item, bd_item_add
from aiogram import types
from bot_sys import bot_bd, keyboard, user_access, bd_table
from bot_modules import mod_table_operate, mod_simple_message
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.dispatcher import Dispatcher
import sqlite3
class FSMCreateProject(StatesGroup):
name = State()
@ -25,7 +20,7 @@ class FSMEditProjectPhotoItem(StatesGroup):
class FSMEditProjectNameItem(StatesGroup):
item_field = State()
class FSMEditProjectDeskItem(StatesGroup):
class FSMEditProjectDescItem(StatesGroup):
item_field = State()
class FSMEditProjectAccessItem(StatesGroup):
@ -42,314 +37,123 @@ photo_field = 'projectPhoto'
access_field = 'projectAccess'
create_datetime_field = 'projectCreateDateTime'
init_bd_cmds = [f'''CREATE TABLE IF NOT EXISTS {table_name}(
{key_name} INTEGER PRIMARY KEY,
{name_field} TEXT,
{desc_field} TEXT,
{photo_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT
)''',
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_new}=va', '{user_access.user_access_group_new}=va');"
]
def MSG(a_MessageName, a_MessageDesc):
def UpdateMSG(a_Message : user_messages.Message):
print(a_Message.m_MessageName, a_Message.m_MessageDesc)
globals()[a_Message.m_MessageName] = a_Message
user_messages.MSG(a_MessageName, a_MessageDesc, UpdateMSG, log.GetTimeNow())
table = bd_table.Table(table_name, [
bd_table.TableField(key_name, bd_table.TableFieldDestiny.KEY, bd_table.TableFieldType.INT),
bd_table.TableField(name_field, bd_table.TableFieldDestiny.NAME, bd_table.TableFieldType.STR),
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),
])
init_access = f'{user_access.user_access_group_new}=va'
fsm = {
mod_table_operate.FSMs.CREATE: FSMCreateProject,
mod_table_operate.FSMs.EDIT_NAME: FSMEditProjectNameItem,
mod_table_operate.FSMs.EDIT_DESC: FSMEditProjectDescItem,
mod_table_operate.FSMs.EDIT_PHOTO: FSMEditProjectPhotoItem,
mod_table_operate.FSMs.EDIT_ACCESS: FSMEditProjectAccessItem,
}
# ---------------------------------------------------------
# Сообщения
projects_button_name = "🟥 Проекты"
MSG('base_project_message','''
<b>🟥 Проекты</b>
''')
list_project_button_name = "📃 Список проектов"
MSG('select_project_message','''
# Сообщения и кнопки
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: '''
Пожалуйста, выберите проект:
''')
MSG('error_find_proj_message','''
''',
mod_table_operate.Messages.ERROR_FIND: '''
Ошибка, проект не найден
''')
MSG('project_open_message',f'''
''',
mod_table_operate.Messages.OPEN: f'''
<b>Проект: #{name_field}</b>
#{desc_field}
Время создания: #{create_datetime_field}
''')
# Создание проекта
add_project_button_name = "✅ Добавить проект"
MSG('project_create_name_message','''
''',
mod_table_operate.Messages.CREATE_NAME: '''
Создание проекта. Шаг 1
Введите название проекта:
''')
MSG('project_create_desc_message','''
''',
mod_table_operate.Messages.CREATE_DESC: '''
Создание проекта. Шаг 2
Введите описание проекта:
''')
MSG('project_create_photo_message','''
''',
mod_table_operate.Messages.CREATE_PHOTO: '''
Создание проекта. Шаг 3
Загрузите обложку для проекта (Фото):
Она будет отображаться в его описании.
''')
MSG('project_success_create_message','''✅ Проект успешно добавлен!''')
# Редактирование проекта.
edit_project_button_name = "🛠 Редактировать проект"
MSG('project_start_edit_message', '''
''',
mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Проект успешно добавлен!''',
mod_table_operate.Messages.START_EDIT: '''
Пожалуйста, выберите действие:
''')
MSG('project_select_to_edit_message','''
''',
mod_table_operate.Messages.SELECT_TO_EDIT: '''
Выберите проект, который вы хотите отредактировать.
''')
edit_project_photo_button_name = "☐ Изменить изображение в проекте"
MSG('project_edit_photo_message','''
''',
mod_table_operate.Messages.EDIT_PHOTO: '''
Загрузите новую обложку для проекта (Фото):
Она будет отображаться в его описании.
''')
edit_project_name_button_name = "≂ Изменить название в проекте"
MSG('project_edit_name_message',f'''
''',
mod_table_operate.Messages.EDIT_NAME: f'''
Текущее название проекта:
#{name_field}
Введите новое название проекта:
''')
edit_project_desc_button_name = "𝌴 Изменить описание в проекте"
MSG('project_edit_desc_message',f'''
''',
mod_table_operate.Messages.EDIT_DESC: f'''
Текущее описание проекта:
#{desc_field}
Введите новое описание проекта:
''')
edit_project_access_button_name = "✋ Изменить доступ к проекту"
MSG('project_edit_access_message',f'''
''',
mod_table_operate.Messages.EDIT_ACCESS: f'''
Текущий доступ к проекту:
#{access_field}
{user_access.user_access_readme}
Введите новую строку доступа:
''')
MSG('project_success_edit_message','''✅ Проект успешно отредактирован!''')
# Удаление проекта
del_project_button_name = "❌ Удалить проект"
MSG('project_select_to_delete_message','''
''',
mod_table_operate.Messages.SUCCESS_EDIT: '''✅ Проект успешно отредактирован!''',
mod_table_operate.Messages.SELECT_TO_DELETE: '''
Выберите проект, который вы хотите удалить.
Все задачи и потребности в этом проекте так же будут удалены!
''')
MSG('project_success_delete_message','''✅ Проект успешно удалён!''')
# ---------------------------------------------------------
# Работа с кнопками
''',
mod_table_operate.Messages.SUCCESS_DELETE: '''✅ Проект успешно удалён!''',
}
def GetEditProjectKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = GetModuleButtons() + [
keyboard.ButtonWithAccess(edit_project_photo_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_project_name_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_project_desc_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_project_access_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
class ModuleProjects(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 GetStartProjectKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(list_project_button_name, user_access.AccessMode.VIEW, GetAccess()),
keyboard.ButtonWithAccess(add_project_button_name, user_access.AccessMode.ADD, GetAccess()),
keyboard.ButtonWithAccess(del_project_button_name, user_access.AccessMode.DELETE, GetAccess()),
keyboard.ButtonWithAccess(edit_project_button_name, user_access.AccessMode.EDIT, GetAccess())
]
mods = [start, tasks, needs, comments]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetName(self):
return module_name
def GetViewItemInlineKeyboardTemplate(a_ItemID):
def GetViewItemInlineKeyboard(a_Message, a_UserGroups):
cur_buttons = [
keyboard.InlineButton(tasks.list_task_button_name, tasks.select_tasks_prefix, a_ItemID, GetAccess(), user_access.AccessMode.VIEW),
def GetModuleButtons(self):
return super().GetModuleButtons() + [
keyboard.ButtonWithAccess(self.GetButton(mod_table_operate.ButtonNames.LIST), user_access.AccessMode.VIEW, self.GetAccess()),
]
return keyboard.MakeInlineKeyboard(cur_buttons, a_UserGroups)
return GetViewItemInlineKeyboard
# ---------------------------------------------------------
# Обработка сообщений
# стартовое сообщение
async def ProjectsOpen(a_Message : types.message, state = None):
return simple_message.WorkFuncResult(base_project_message)
def GetButtonNameAndKeyValueAndAccess(a_Item):
# projectName projectID projectAccess
return a_Item[1], a_Item[0], a_Item[4]
def ShowMessageTemplate(a_StringMessage, keyboard_template_func = None):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
msg = str(a_StringMessage).\
replace(f'#{name_field}', a_Item[1]).\
replace(f'#{desc_field}', a_Item[2]).\
replace(f'#{create_datetime_field}', a_Item[5]).\
replace(f'#{access_field}', a_Item[4])
keyboard_func = None
if keyboard_template_func:
keyboard_func = keyboard_template_func(a_Item[0])
return simple_message.WorkFuncResult(msg, photo_id = a_Item[3], item_access = a_Item[4], keyboard_func = keyboard_func)
return ShowMessage
def SimpleMessageTemplate(a_StringMessage):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
return simple_message.WorkFuncResult(a_StringMessage)
return ShowMessage
# Удаление проекта
async def ProjectPreDelete(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
access = a_Item[4]
return simple_message.WorkFuncResult('', None, item_access = access)
async def ProjectPostDelete(a_CallbackQuery : types.CallbackQuery, a_ItemID):
log.Success(f'Проект №{a_ItemID} был удалён пользователем {a_CallbackQuery.from_user.id}.')
#TODO: удалить вложенные
return simple_message.WorkFuncResult(project_success_delete_message)
# ---------------------------------------------------------
# Работа с базой данных проектов
def AddBDItemFunc(a_ItemData, a_UserID):
res, error = bot_bd.SQLRequestToBD(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], access.GetItemDefaultAccessForModule(module_name) + f";{a_UserID}=+"))
if error:
log.Error(f'Пользоватлель {a_UserID}. Ошибка добавления записи в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
else:
log.Success(f'Пользоватлель {a_UserID}. Добавлена запись в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
return res, error
# ---------------------------------------------------------
# API
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [
keyboard.ButtonWithAccess(projects_button_name, user_access.AccessMode.VIEW, GetAccess()),
keyboard.ButtonWithAccess(list_project_button_name, user_access.AccessMode.VIEW, GetAccess()),
]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
defaul_keyboard_func = GetStartProjectKeyboardButtons
# Список проектов
dp.register_message_handler(simple_message.SimpleMessageTemplate(ProjectsOpen, defaul_keyboard_func, GetAccess), text = projects_button_name)
bd_item_view.FirstSelectAndShowBDItemRegisterHandlers(dp, \
list_project_button_name, \
table_name, \
key_name, \
ShowMessageTemplate(project_open_message, GetViewItemInlineKeyboardTemplate), \
GetButtonNameAndKeyValueAndAccess, \
select_project_message, \
GetAccess, \
defaul_keyboard_func\
)
# Удаление проекта
bd_item_delete.DeleteBDItemRegisterHandlers(dp, \
None, \
bd_item.GetCheckForTextFunc(del_project_button_name), \
table_name, \
key_name, \
None, \
ProjectPreDelete, \
ProjectPostDelete, \
GetButtonNameAndKeyValueAndAccess, \
select_project_message, \
GetAccess, \
defaul_keyboard_func\
)
# Добавление проекта
bd_item_add.AddBDItem3RegisterHandlers(dp, \
bd_item.GetCheckForTextFunc(add_project_button_name), \
FSMCreateProject,\
FSMCreateProject.name,\
FSMCreateProject.desc, \
FSMCreateProject.photo,\
AddBDItemFunc, \
SimpleMessageTemplate(project_create_name_message), \
SimpleMessageTemplate(project_create_desc_message), \
SimpleMessageTemplate(project_create_photo_message), \
SimpleMessageTemplate(project_success_create_message), \
None,\
None, \
None, \
name_field, \
desc_field, \
photo_field, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
GetStartProjectKeyboardButtons\
)
# Редактирование проекта
edit_keyboard_func = GetEditProjectKeyboardButtons
def RegisterEdit(a_ButtonName, a_FSM, a_EditMessage, a_FieldName, a_FieldType, a_AccessMode = user_access.AccessMode.EDIT):
bd_item_edit.EditBDItemRegisterHandlers(dp, \
None, \
a_FSM, \
bd_item.GetCheckForTextFunc(a_ButtonName), \
project_select_to_edit_message, \
ShowMessageTemplate(a_EditMessage), \
ShowMessageTemplate(project_success_edit_message), \
table_name, \
key_name, \
None, \
a_FieldName, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
edit_keyboard_func, \
access_mode = a_AccessMode, \
field_type = a_FieldType\
)
dp.register_message_handler(simple_message.InfoMessageTemplate(project_start_edit_message, edit_keyboard_func, GetAccess, access_mode = user_access.AccessMode.EDIT), text = edit_project_button_name)
RegisterEdit(edit_project_photo_button_name, FSMEditProjectPhotoItem, project_edit_photo_message, photo_field, bd_item.FieldType.photo)
RegisterEdit(edit_project_name_button_name, FSMEditProjectNameItem, project_edit_name_message, name_field, bd_item.FieldType.text)
RegisterEdit(edit_project_desc_button_name, FSMEditProjectDeskItem, project_edit_desc_message, desc_field, bd_item.FieldType.text)
RegisterEdit(edit_project_access_button_name, FSMEditProjectAccessItem, project_edit_access_message, access_field, bd_item.FieldType.text)

104
bot_modules/start.py

@ -3,76 +3,50 @@
# Стартовое меню
from bot_sys import log, config, keyboard, user_access, user_messages
from bot_modules import profile, projects, groups, access, backup, languages
from template import simple_message
from bot_sys import user_access
from bot_modules import mod_simple_message, profile
from template import bd_item
from aiogram.dispatcher import Dispatcher
def MSG(a_MessageName, a_MessageDesc):
def UpdateMSG(a_Message : user_messages.Message):
print(a_Message.m_MessageName, a_Message.m_MessageDesc)
globals()[a_Message.m_MessageName] = a_Message
user_messages.MSG(a_MessageName, a_MessageDesc, UpdateMSG, log.GetTimeNow())
# ---------------------------------------------------------
# БД
module_name = 'start'
init_bd_cmds = [
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_all}=+', '{user_access.user_access_group_all}=+');"
]
button_names = {
mod_simple_message.ButtonNames.START: "☰ Главное меню",
}
# ---------------------------------------------------------
# Сообщения
MSG('start_message', '''
messages = {
mod_simple_message.Messages.START: f'''
<b>Добро пожаловать!</b>
Выберите возможные действия на кнопках ниже '''
)
start_menu_button_name = "☰ Главное меню"
# ---------------------------------------------------------
# Работа с кнопками
def GetStartKeyboardButtons(a_Message, a_UserGroups):
mods = [profile, projects, groups, access, backup, languages]
return keyboard.MakeKeyboardForMods(mods, a_UserGroups)
# ---------------------------------------------------------
# Обработка сообщений
# Первичное привестивие
async def StartMenu(a_Message, state = None):
user_id = str(a_Message.from_user.id)
user_name = str(a_Message.from_user.username)
first_name = str(a_Message.from_user.first_name)
last_name = str(a_Message.from_user.last_name)
is_bot = str(a_Message.from_user.is_bot)
language_code = str(a_Message.from_user.language_code)
profile.AddUser(user_id, user_name, first_name, last_name, is_bot, language_code)
log.Info(f'Пользователь {user_id} {user_name} авторизовался в боте. Полные данные {a_Message.from_user}.')
return simple_message.WorkFuncResult(start_message)
# ---------------------------------------------------------
# API
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Имена доступных кнопок
def GetModuleButtons():
return [keyboard.ButtonWithAccess(start_menu_button_name, user_access.AccessMode.VIEW, GetAccess())]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
dp.register_message_handler(simple_message.SimpleMessageTemplate(StartMenu, GetStartKeyboardButtons, GetAccess), commands = ['start'])
dp.register_message_handler(simple_message.SimpleMessageTemplate(StartMenu, GetStartKeyboardButtons, GetAccess), text = start_menu_button_name)
Выберите возможные действия на кнопках ниже ''',
}
init_access = f'{user_access.user_access_group_all}=+'
class ModuleStart(mod_simple_message.SimpleMessageModule):
def __init__(self, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log):
super().__init__(messages, button_names, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_Log)
def GetName(self):
return module_name
# Основной обработчик главного сообщения
async def StartMessageHandler(self, a_Message, state = None):
user_id = str(a_Message.from_user.id)
user_name = str(a_Message.from_user.username)
first_name = str(a_Message.from_user.first_name)
last_name = str(a_Message.from_user.last_name)
is_bot = str(a_Message.from_user.is_bot)
language_code = str(a_Message.from_user.language_code)
profile.AddUser(self.m_Bot, user_id, user_name, first_name, last_name, is_bot, language_code)
self.m_Log.Info(f'Пользователь {user_id} {user_name} авторизовался в боте. Полные данные {a_Message.from_user}.')
return await super().StartMessageHandler(a_Message, state)
def RegisterHandlers(self):
super().RegisterHandlers()
self.m_Bot.RegisterMessageHandler(
self.m_StartMessageHandler,
None,
commands = ['start']
)

371
bot_modules/tasks.py

@ -3,16 +3,11 @@
# Задачи
from bot_sys import bot_bd, log, keyboard, user_access
from bot_modules import start, access, groups, projects, needs, comments
from template import bd_item_view, simple_message, bd_item_delete, bd_item_edit, bd_item, bd_item_add, bd_item_select
from aiogram import types
from bot_sys import bot_bd, keyboard, user_access, bd_table
from bot_modules import mod_table_operate, mod_simple_message
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.dispatcher import Dispatcher
import sqlite3
class FSMCreateTask(StatesGroup):
name = State()
@ -20,19 +15,15 @@ class FSMCreateTask(StatesGroup):
photo = State()
class FSMEditTaskPhotoItem(StatesGroup):
item_id = State()
item_field = State()
class FSMEditTaskNameItem(StatesGroup):
item_id = State()
item_field = State()
class FSMEditTaskDescItem(StatesGroup):
item_id = State()
item_field = State()
class FSMEditTaskAccessItem(StatesGroup):
item_id = State()
item_field = State()
# ---------------------------------------------------------
# БД
@ -47,327 +38,117 @@ access_field = 'taskAccess'
create_datetime_field = 'taskCreateDateTime'
parent_id_field = 'projectID'
init_bd_cmds = [f'''CREATE TABLE IF NOT EXISTS {table_name}(
{key_name} INTEGER PRIMARY KEY,
{name_field} TEXT,
{desc_field} TEXT,
{photo_field} TEXT,
{access_field} TEXT,
{create_datetime_field} TEXT,
{parent_id_field} INTEGER
)''',
f"INSERT OR IGNORE INTO module_access (modName, modAccess, itemDefaultAccess) VALUES ('{module_name}', '{user_access.user_access_group_new}=va', '{user_access.user_access_group_new}=va');"
]
select_tasks_prefix = ''
table = bd_table.Table(table_name, [
bd_table.TableField(key_name, bd_table.TableFieldDestiny.KEY, bd_table.TableFieldType.INT),
bd_table.TableField(name_field, bd_table.TableFieldDestiny.NAME, bd_table.TableFieldType.STR),
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),
bd_table.TableField(parent_id_field, bd_table.TableFieldDestiny.PARENT_ID, bd_table.TableFieldType.INT),
])
init_access = f'{user_access.user_access_group_new}=va'
fsm = {
mod_table_operate.FSMs.CREATE: FSMCreateTask,
mod_table_operate.FSMs.EDIT_NAME: FSMEditTaskNameItem,
mod_table_operate.FSMs.EDIT_DESC: FSMEditTaskDescItem,
mod_table_operate.FSMs.EDIT_PHOTO: FSMEditTaskPhotoItem,
mod_table_operate.FSMs.EDIT_ACCESS: FSMEditTaskAccessItem,
}
# ---------------------------------------------------------
# Сообщения
tasks_button_name = "✎ Задачи"
base_task_message = '''
<b> Задачи</b>
'''
list_task_button_name = "📃 Список задач"
select_task_message = '''
# Сообщения и кнопки
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: '''
Пожалуйста, выберите задачу:
'''
error_find_proj_message = '''
''',
mod_table_operate.Messages.ERROR_FIND: '''
Ошибка, задача не найдена
'''
task_open_message = f'''
''',
mod_table_operate.Messages.OPEN: f'''
<b>Задача: #{name_field}</b>
#{desc_field}
Время создания: #{create_datetime_field}
'''
# Создание задачи
add_task_button_name = "☑ Добавить задачу"
task_create_name_message = '''
''',
mod_table_operate.Messages.CREATE_NAME: '''
Создание задачи. Шаг 1
Введите название задачи:
'''
task_create_desc_message = '''
''',
mod_table_operate.Messages.CREATE_DESC: '''
Создание задачи. Шаг 2
Введите описание задачи:
'''
task_create_photo_message = '''
''',
mod_table_operate.Messages.CREATE_PHOTO: '''
Создание задачи. Шаг 3
Загрузите обложку для задачи (Фото):
Она будет отображаться в её описании.
'''
task_success_create_message = '''✅ Задача успешно добавлена!'''
# Редактирование задачи.
edit_task_button_name = "🛠 Редактировать задачу"
task_start_edit_message= '''
''',
mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Задача успешно добавлена!''',
mod_table_operate.Messages.START_EDIT: '''
Пожалуйста, выберите действие:
'''
task_select_to_edit_message = '''
''',
mod_table_operate.Messages.SELECT_TO_EDIT: '''
Выберите задачу, которую вы хотите отредактировать.
'''
edit_task_photo_button_name = "☐ Изменить изображение у задачи"
task_edit_photo_message = '''
''',
mod_table_operate.Messages.EDIT_PHOTO: '''
Загрузите новую обложку для задачи (Фото):
Она будет отображаться в её описании.
'''
edit_task_name_button_name = "≂ Изменить название у задачи"
task_edit_name_message = f'''
''',
mod_table_operate.Messages.EDIT_NAME: f'''
Текущее название задачи:
#{name_field}
Введите новое название задачи:
'''
edit_task_desc_button_name = "𝌴 Изменить описание у задачи"
task_edit_desc_message = f'''
''',
mod_table_operate.Messages.EDIT_DESC: f'''
Текущее описание задачи:
#{desc_field}
Введите новое описание задачи:
'''
edit_task_access_button_name = "✋ Изменить доступ к задаче"
task_edit_access_message = f'''
''',
mod_table_operate.Messages.EDIT_ACCESS: f'''
Текущий доступ к задаче:
#{access_field}
{user_access.user_access_readme}
Введите новую строку доступа:
'''
task_success_edit_message = '''✅ Задача успешно отредактирована!'''
# Удаление задачи
del_task_button_name = "❌ Удалить задачу"
task_select_to_delete_message = '''
''',
mod_table_operate.Messages.SUCCESS_EDIT: '''✅ Задача успешно отредактирован!''',
mod_table_operate.Messages.SELECT_TO_DELETE: '''
Выберите задачу, которую вы хотите удалить.
Все потребности в этой задачае так же будут удалены!
'''
task_success_delete_message = '''✅ Задача успешно удалена!'''
# ---------------------------------------------------------
# Работа с кнопками
def GetEditTaskKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = GetModuleButtons() + [
keyboard.ButtonWithAccess(edit_task_photo_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_task_name_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_task_desc_button_name, user_access.AccessMode.EDIT, GetAccess()),
keyboard.ButtonWithAccess(edit_task_access_button_name, user_access.AccessMode.ACCEES_EDIT, GetAccess()),
]
mods = [start]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetStartTaskKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(list_task_button_name, user_access.AccessMode.VIEW, GetAccess()),
keyboard.ButtonWithAccess(add_task_button_name, user_access.AccessMode.ADD, GetAccess()),
keyboard.ButtonWithAccess(del_task_button_name, user_access.AccessMode.DELETE, GetAccess()),
keyboard.ButtonWithAccess(edit_task_button_name, user_access.AccessMode.EDIT, GetAccess())
]
mods = [start, projects, needs, comments]
return keyboard.MakeKeyboard(keyboard.GetButtons(mods) + cur_buttons, a_UserGroups)
def GetViewItemInlineKeyboardTemplate(a_ItemID):
def GetViewItemInlineKeyboard(a_Message, a_UserGroups):
cur_buttons = [
keyboard.InlineButton(needs.list_need_button_name, needs.select_needs_prefix, a_ItemID, GetAccess(), user_access.AccessMode.VIEW),
]
return keyboard.MakeInlineKeyboard(cur_buttons, a_UserGroups)
return GetViewItemInlineKeyboard
# ---------------------------------------------------------
# Обработка сообщений
# стартовое сообщение
async def TasksOpen(a_Message : types.message, state = None):
return simple_message.WorkFuncResult(base_task_message)
def GetButtonNameAndKeyValueAndAccess(a_Item):
# taskName taskID taskAccess
return a_Item[1], a_Item[0], a_Item[4]
def ShowMessageTemplate(a_StringMessage, keyboard_template_func = None):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
msg = a_StringMessage.\
replace(f'#{name_field}', a_Item[1]).\
replace(f'#{desc_field}', a_Item[2]).\
replace(f'#{create_datetime_field}', a_Item[5]).\
replace(f'#{access_field}', a_Item[4])
keyboard_func = None
if keyboard_template_func:
keyboard_func = keyboard_template_func(a_Item[0])
return simple_message.WorkFuncResult(msg, photo_id = a_Item[3], item_access = a_Item[4], keyboard_func = keyboard_func)
return ShowMessage
def SimpleMessageTemplate(a_StringMessage):
async def ShowMessage(a_CallbackQuery : types.CallbackQuery, a_Item):
return simple_message.WorkFuncResult(a_StringMessage)
return ShowMessage
# Удаление задачи
async def TaskPreDelete(a_CallbackQuery : types.CallbackQuery, a_Item):
if (len(a_Item) < 6):
return simple_message.WorkFuncResult(error_find_proj_message)
access = a_Item[4]
return simple_message.WorkFuncResult('', None, item_access = access)
async def TaskPostDelete(a_CallbackQuery : types.CallbackQuery, a_ItemID):
log.Success(f'Задача №{a_ItemID} была удалена пользователем {a_CallbackQuery.from_user.id}.')
#TODO: удалить вложенные
return simple_message.WorkFuncResult(task_success_delete_message)
# ---------------------------------------------------------
# Работа с базой данных задач
def AddBDItemFunc(a_ItemData, a_UserID):
res, error = bot_bd.SQLRequestToBD(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], access.GetItemDefaultAccessForModule(module_name) + f";{a_UserID}=+", a_ItemData[parent_id_field]))
if error:
log.Error(f'Пользоватлель {a_UserID}. Ошибка добавления записи в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
else:
log.Success(f'Пользоватлель {a_UserID}. Добавлена запись в таблицу {table_name} ({a_ItemData[photo_field]}, {a_ItemData[name_field]}, {a_ItemData[desc_field]}, {access.GetItemDefaultAccessForModule(module_name)}).')
return res, error
# ---------------------------------------------------------
# API
# Инициализация БД
def GetInitBDCommands():
return init_bd_cmds
def GetAccess():
return access.GetAccessForModule(module_name)
# Доступные кнопки
def GetModuleButtons():
return [keyboard.ButtonWithAccess(tasks_button_name, user_access.AccessMode.VIEW, GetAccess())]
# Обработка кнопок
def RegisterHandlers(dp : Dispatcher):
defaul_keyboard_func = GetStartTaskKeyboardButtons
def RegisterSelectParent(a_ButtonName, access_mode):
a_PrefixBase = a_ButtonName
return bd_item_select.FirstSelectBDItemRegisterHandlers(dp, \
a_PrefixBase, \
a_ButtonName, \
projects.table_name, \
projects.key_name, \
projects.GetButtonNameAndKeyValueAndAccess, \
projects.select_project_message, \
projects.GetAccess, access_mode = access_mode\
)
# Стартовое сообщение
dp.register_message_handler(simple_message.SimpleMessageTemplate(TasksOpen, defaul_keyboard_func, GetAccess), text = tasks_button_name)
# Список задач
a_Prefix = RegisterSelectParent(list_task_button_name, user_access.AccessMode.VIEW)
bd_item_view.LastSelectAndShowBDItemRegisterHandlers(dp, \
a_Prefix, parent_id_field, \
table_name, key_name, \
ShowMessageTemplate(task_open_message, GetViewItemInlineKeyboardTemplate), \
GetButtonNameAndKeyValueAndAccess, \
select_task_message, \
GetAccess, \
defaul_keyboard_func, \
access_mode = user_access.AccessMode.VIEW\
)
global select_tasks_prefix
select_tasks_prefix = a_Prefix
# Удаление задачи
a_Prefix = RegisterSelectParent(del_task_button_name, user_access.AccessMode.DELETE)
bd_item_delete.DeleteBDItemRegisterHandlers(dp, \
a_Prefix, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
table_name, \
key_name, \
parent_id_field, \
TaskPreDelete, \
TaskPostDelete, \
GetButtonNameAndKeyValueAndAccess, \
select_task_message, \
GetAccess, \
defaul_keyboard_func\
)
# Добавление задачи
a_Prefix = RegisterSelectParent(add_task_button_name, user_access.AccessMode.ADD)
bd_item_add.AddBDItem3RegisterHandlers(dp, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
FSMCreateTask, \
FSMCreateTask.name,\
FSMCreateTask.desc, \
FSMCreateTask.photo,\
AddBDItemFunc, \
SimpleMessageTemplate(task_create_name_message), \
SimpleMessageTemplate(task_create_desc_message), \
SimpleMessageTemplate(task_create_photo_message), \
SimpleMessageTemplate(task_success_create_message), \
a_Prefix,\
projects.table_name, \
projects.key_name, \
name_field, \
desc_field, \
photo_field, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
GetStartTaskKeyboardButtons\
)
def RegisterEdit(a_ButtonName, a_FSM, a_EditMessage, a_FieldName, a_FieldType, a_AccessMode = user_access.AccessMode.EDIT):
a_Prefix = RegisterSelectParent(a_ButtonName, a_AccessMode)
bd_item_edit.EditBDItemRegisterHandlers(dp, \
a_Prefix, \
a_FSM, \
bd_item.GetCheckForPrefixFunc(a_Prefix), \
task_select_to_edit_message, \
ShowMessageTemplate(a_EditMessage), \
ShowMessageTemplate(task_success_edit_message), \
table_name, \
key_name, \
parent_id_field, \
a_FieldName, \
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
edit_keyboard_func, \
access_mode = a_AccessMode, \
field_type = a_FieldType\
)
Все потребности в этой задаче так же будут удалены!
''',
mod_table_operate.Messages.SUCCESS_DELETE: '''✅ Задача успешно удалёна!''',
}
# Редактирование задачи
edit_keyboard_func = GetEditTaskKeyboardButtons
dp.register_message_handler(simple_message.InfoMessageTemplate(task_start_edit_message, edit_keyboard_func, GetAccess, access_mode = user_access.AccessMode.EDIT), text = edit_task_button_name)
class ModuleTasks(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)
RegisterEdit(edit_task_photo_button_name, FSMEditTaskPhotoItem, task_edit_photo_message, photo_field, bd_item.FieldType.photo)
RegisterEdit(edit_task_name_button_name, FSMEditTaskNameItem, task_edit_name_message, name_field, bd_item.FieldType.text)
RegisterEdit(edit_task_desc_button_name, FSMEditTaskDescItem, task_edit_desc_message, desc_field, bd_item.FieldType.text)
RegisterEdit(edit_task_access_button_name, FSMEditTaskAccessItem, task_edit_access_message, access_field, bd_item.FieldType.text)
def GetName(self):
return module_name

104
bot_sys/aiogram_bot.py

@ -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)

125
bot_sys/bd_table.py

@ -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'

30
bot_sys/bot_bd.py

@ -6,30 +6,21 @@ from bot_sys import log
# Работа с базой данных
# Имя файла БД
g_bd_file_name = 'bot.db'
def GetBDFileName():
return g_bd_file_name
# ---------------------------------------------------------
# Функции работы с базой
# ---------------------------------------------------------
def GetBDDateTimeNow():
return 'datetime(\'now\')'
def BDExecute(a_Commands):
for cmd in a_Commands:
SQLRequestToBD(cmd, commit = True)
def SelectBDTemplate(a_Bot, a_TableName):
def SelectBD():
return a_Bot.SQLRequest(f'SELECT * FROM {a_TableName}')
return SelectBD
def SelectBDTemplate(a_TableName):
def RequestSelectTemplate(a_Bot, a_TableName):
def SelectBD():
return SQLRequestToBD(f'SELECT * FROM {a_TableName}')
return a_Bot.SQLRequest(f'SELECT * FROM {a_TableName}')
return SelectBD
def SQLRequestToBD(a_Request : str, commit = False, return_error = False, param = None):
db = sqlite3.connect(GetBDFileName())
def SQLRequest(a_Log, a_BDFileName, a_Request : str, commit = False, return_error = False, param = None):
db = sqlite3.connect(a_BDFileName)
cursor = db.cursor()
result = []
error = None
@ -42,11 +33,12 @@ def SQLRequestToBD(a_Request : str, commit = False, return_error = False, param
if commit:
db.commit()
except sqlite3.Error as e:
log.Error(f'Ошибка при обработке запроса [{a_Request}]:{str(e)}')
a_Log.Error(f'Ошибка при обработке запроса [{a_Request}]:{str(e)}')
error = "Ошибка sqlite3:" + str(e)
cursor.close()
db.close()
if not error and commit: log.Success(f'Выполнен запрос [{a_Request}]')
if not error and commit:
a_Log.Success(f'Выполнен запрос [{a_Request}]')
if return_error:
return result, error
return result

83
bot_sys/bot_messages.py

@ -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

38
bot_sys/interfaces.py

@ -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

65
bot_sys/keyboard.py

@ -4,8 +4,9 @@
# Работа с кнопками и клавиатурой
from bot_sys import user_access
from aiogram import types, Bot, Dispatcher
from aiogram.types import ReplyKeyboardRemove, ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
from aiogram import types
class ButtonWithAccess:
def __init__(self, a_Label, a_AccessMode : user_access.AccessMode, a_AccessString):
@ -24,29 +25,39 @@ def GetButtons(a_ModList):
import math
def Chunks(a_List, a_ChunkSize):
chunk_list = []
for i in range(0, len(a_List), a_ChunkSize):
yield a_List[i: i + a_ChunkSize]
chunk_list += [a_List[i: i + a_ChunkSize]]
return chunk_list
def GetButtonInRowCount(a_AllKeyCount):
return min(max(int(math.sqrt(a_AllKeyCount) // 1), 1), 4)
return min(max(int(math.sqrt(a_AllKeyCount) // 1), 1), 3)
def MakeKeyboard(a_ButtonList : [ButtonWithAccess], a_UserGroups):
# TODO перенести KeyboardButton в MakeAiogramKeyboard
def MakeButtons(a_Bot, a_ButtonList : [ButtonWithAccess], a_UserGroups):
buttons = []
for b in a_ButtonList:
if user_access.CheckAccessString(b.access_string, a_UserGroups, b.access_mode):
buttons += [types.KeyboardButton(b.label)]
if not b.label:
continue
label = str(b.label)
if user_access.CheckAccess(a_Bot.GetRootIDs(), b.access_string, a_UserGroups, b.access_mode):
buttons += [types.KeyboardButton(label)]
step = GetButtonInRowCount(len(buttons))
key = types.ReplyKeyboardMarkup(keyboard=Chunks(buttons, step), resize_keyboard = True)
return key
return Chunks(buttons, step)
def MakeKeyboardRemove():
return types.ReplyKeyboardRemove()
def MakeKeyboard(a_ButtonList : [ButtonWithAccess], a_UserGroups):
return MakeAiogramKeyboard(MakeButtons(a_ButtonList, a_UserGroups))
def MakeKeyboardForMods(a_ModList, a_UserGroups):
buttons = GetButtons(a_ModList)
return MakeKeyboard(buttons, a_UserGroups)
class InlineButton:
def __init__(self, a_Label, a_CallBackData):
self.label = a_Label
self.callback_data = str(a_CallBackData)
class InlineButtonWithAccess:
def __init__(self, a_Label, a_CallBackPrefix, a_CallBackData, a_AccessString, a_AccessMode):
self.label = a_Label
self.callback_prefix = a_CallBackPrefix
@ -54,12 +65,36 @@ class InlineButton:
self.access_string = a_AccessString
self.access_mode = a_AccessMode
def MakeInlineKeyboard(a_ButtonList : [InlineButton], a_UserGroups):
def MakeInlineKeyboardButtons(a_Bot, a_ButtonList : [InlineButtonWithAccess], a_UserGroups):
buttons = []
for b in a_ButtonList:
if user_access.CheckAccessString(b.access_string, a_UserGroups, b.access_mode):
buttons += [types.InlineKeyboardButton(text = b.label, callback_data = f'{b.callback_prefix}{b.callback_data}')]
if user_access.CheckAccess(a_Bot.GetRootIDs(), b.access_string, a_UserGroups, b.access_mode):
data = f'{b.callback_prefix}{b.callback_data}'
assert len(data) < 41 # Телеграм больше не поддерживает
buttons += [InlineButton(b.label, data)]
step = GetButtonInRowCount(len(buttons))
inline_keyboard = InlineKeyboardMarkup(inline_keyboard=Chunks(buttons, step))
return inline_keyboard
return Chunks(buttons, step)
# -------------------------------
def MakeKeyboardRemove():
return types.ReplyKeyboardRemove()
def MakeAiogramInlineKeyboards(a_ButtonList : [InlineButton]):
buttons = []
for row in a_ButtonList:
r = []
for b in row:
r += [types.InlineKeyboardButton(text = str(b.label), callback_data = b.callback_data)]
buttons += [r]
button_list_chunks = Chunks(buttons, 20)
result = []
for c in button_list_chunks:
result += [InlineKeyboardMarkup(inline_keyboard=c)]
return result
def MakeAiogramKeyboard(a_ButtonList : [[str]]):
return types.ReplyKeyboardMarkup(keyboard=a_ButtonList, resize_keyboard = True)

82
bot_sys/log.py

@ -10,48 +10,52 @@
# Error - Ошибка.
# Success - Успех.
# Файл лога
g_log_file_name = 'log.txt'
from bot_sys import config
import colorama
import datetime
colorama.init()
def GetTimeNow():
return datetime.datetime.now()
def GetTime():
now = GetTimeNow()
time = now.strftime(f"[%d.%m.%Y, %H:%M]")
return time
def Info(a_LogMessage):
time = GetTime()
WriteToFile(f'{time} | {a_LogMessage}')
print(f"{time} {colorama.Back.BLUE}{colorama.Style.BRIGHT} ИНФО {colorama.Style.RESET_ALL} | {a_LogMessage}")
def Warn(a_LogMessage):
time = GetTime()
WriteToFile(f'{time} | {a_LogMessage}')
print(f"{time} {colorama.Back.YELLOW}{colorama.Style.BRIGHT} ВНИМАНИЕ {colorama.Style.RESET_ALL} | {a_LogMessage}")
def Error(a_LogMessage):
time = GetTime()
WriteToFile(f'{time} | {a_LogMessage}')
print(f"{time} {colorama.Back.RED}{colorama.Style.BRIGHT} ОШИБКА {colorama.Style.RESET_ALL} | {a_LogMessage}")
def Success(a_LogMessage):
time = GetTime()
WriteToFile(f'{time} | {a_LogMessage}')
print(f"{time} {colorama.Back.GREEN}{colorama.Style.BRIGHT} УСПЕХ {colorama.Style.RESET_ALL} | {a_LogMessage}")
def WriteToFile(a_LogMessage):
if config.g_log_to_file != True:
return
f = open(g_log_file_name, 'a+')
f.write(a_LogMessage)
f.write('\n')
f.close()
class Log:
def __init__(self, a_FileName):
self.m_FileName = a_FileName
def GetFileName(self):
return self.m_FileName
def GetTimeNow(self):
return datetime.datetime.now()
def GetTime(self):
now = self.GetTimeNow()
time = now.strftime(f"[%d.%m.%Y, %H:%M]")
return time
def Info(self, a_LogMessage):
time = self.GetTime()
self.WriteToFile(f'{time} | {a_LogMessage}')
print(f"{time} {colorama.Back.BLUE}{colorama.Style.BRIGHT} ИНФО {colorama.Style.RESET_ALL} | {a_LogMessage}")
def Warn(self, a_LogMessage):
time = self.GetTime()
self.WriteToFile(f'{time} | {a_LogMessage}')
print(f"{time} {colorama.Back.YELLOW}{colorama.Style.BRIGHT} ВНИМАНИЕ {colorama.Style.RESET_ALL} | {a_LogMessage}")
def Error(self, a_LogMessage):
time = self.GetTime()
self.WriteToFile(f'{time} | {a_LogMessage}')
print(f"{time} {colorama.Back.RED}{colorama.Style.BRIGHT} ОШИБКА {colorama.Style.RESET_ALL} | {a_LogMessage}")
def Success(self, a_LogMessage):
time = self.GetTime()
self.WriteToFile(f'{time} | {a_LogMessage}')
print(f"{time} {colorama.Back.GREEN}{colorama.Style.BRIGHT} УСПЕХ {colorama.Style.RESET_ALL} | {a_LogMessage}")
def WriteToFile(self, a_LogMessage):
if not self.m_FileName:
return
f = open(self.m_FileName, 'a+')
f.write(a_LogMessage)
f.write('\n')
f.close()

218
bot_sys/user_access.py

@ -54,8 +54,8 @@ def CheckAccessItem(a_AccessItem : str, a_AccessMode : AccessMode):
return False
# Возвращает возможность доступа пользователю a_UserGroups в элемент с правами a_AccessValue по режиму доступа a_AccessMode
def CheckAccessString(a_AccessValue : str, a_UserGroups : UserGroups, a_AccessMode : AccessMode):
if a_UserGroups.user_id in config.GetRootIDs():
def CheckAccess(a_RootIDs, a_AccessValue : str, a_UserGroups : UserGroups, a_AccessMode : AccessMode):
if a_UserGroups.user_id in a_RootIDs:
return True
for i in a_AccessValue.split(';'):
d = i.split('=')
@ -72,99 +72,125 @@ def Test():
assert '1234' in ['123', '1234']
assert not '1234' in ['123', '12345']
# root имеет полный доступ вне зависимости от a_AccessValue и a_UserGroups и a_AccessMode
roots = ['1234']
for am in AccessMode.ADD, AccessMode.DELETE, AccessMode.EDIT, AccessMode.VIEW, AccessMode.ACCEES_EDIT:
assert CheckAccessString('1234=+', UserGroups('1234', []), am)
assert not CheckAccessString('1234=-', UserGroups('1234', []), am)
assert CheckAccessString('1234=+;gr1=+', UserGroups('1234', ['gr1']), am)
assert CheckAccessString('1234=-;gr1=+', UserGroups('1234', ['gr1']), am)
assert not CheckAccessString('1234=+', UserGroups('123', []), am)
assert not CheckAccessString('1234=-', UserGroups('123', []), am)
assert not CheckAccessString('1234=+;gr1=+', UserGroups('123', ['gr']), am)
assert not CheckAccessString('1234=-;gr1=+', UserGroups('123', ['gr']), am)
assert not CheckAccessString('1234=+;gr=+', UserGroups('123', ['gr1']), am)
assert not CheckAccessString('1234=-;gr=+', UserGroups('123', ['gr1']), am)
assert CheckAccessString('123=-;1234=a', UserGroups('1234', []), AccessMode.ADD)
assert CheckAccessString('123=-;1234=d', UserGroups('1234', []), AccessMode.DELETE)
assert CheckAccessString('123=-;1234=e', UserGroups('1234', []), AccessMode.EDIT)
assert CheckAccessString('123=-;1234=r', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert CheckAccessString('123=-;1234=v', UserGroups('1234', []), AccessMode.VIEW)
assert CheckAccessString('123=-;gr1=a', UserGroups('1234', ['gr1']), AccessMode.ADD)
assert CheckAccessString('123=-;gr1=d', UserGroups('1234', ['gr1']), AccessMode.DELETE)
assert CheckAccessString('123=-;gr1=e', UserGroups('1234', ['gr1']), AccessMode.EDIT)
assert CheckAccessString('123=-;gr1=r', UserGroups('1234', ['gr1']), AccessMode.ACCEES_EDIT)
assert CheckAccessString('123=-;gr1=v', UserGroups('1234', ['gr1']), AccessMode.VIEW)
assert CheckAccessString('123=-;1234=daver', UserGroups('1234', []), AccessMode.ADD)
assert CheckAccessString('123=-;1234=dav', UserGroups('1234', []), AccessMode.DELETE)
assert CheckAccessString('123=-;1234=edv', UserGroups('1234', []), AccessMode.EDIT)
assert CheckAccessString('123=-;1234=rav', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert CheckAccessString('123=-;1234=va', UserGroups('1234', []), AccessMode.VIEW)
assert CheckAccessString('123=-;gr1=avr', UserGroups('1234', ['gr1']), AccessMode.ADD)
assert CheckAccessString('123=-;gr1=daver', UserGroups('1234', ['gr1']), AccessMode.DELETE)
assert CheckAccessString('123=-;gr1=eva', UserGroups('1234', ['gr1']), AccessMode.EDIT)
assert CheckAccessString('123=-;gr1=re', UserGroups('1234', ['gr1']), AccessMode.ACCEES_EDIT)
assert CheckAccessString('123=-;gr1=vad', UserGroups('1234', ['gr1']), AccessMode.VIEW)
assert not CheckAccessString('123=-;1234=d', UserGroups('1234', []), AccessMode.ADD)
assert not CheckAccessString('123=-;1234=a', UserGroups('1234', []), AccessMode.DELETE)
assert not CheckAccessString('123=-;1234=r', UserGroups('1234', []), AccessMode.EDIT)
assert not CheckAccessString('123=-;1234=v', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert not CheckAccessString('123=-;1234=e', UserGroups('1234', []), AccessMode.VIEW)
assert not CheckAccessString('123=-;gr1=d', UserGroups('1234', ['gr']), AccessMode.ADD)
assert not CheckAccessString('123=-;gr1=a', UserGroups('1234', ['gr']), AccessMode.DELETE)
assert not CheckAccessString('123=-;gr1=v', UserGroups('1234', ['gr']), AccessMode.EDIT)
assert not CheckAccessString('123=-;gr1=e', UserGroups('1234', ['gr']), AccessMode.ACCEES_EDIT)
assert not CheckAccessString('123=-;gr1=r', UserGroups('1234', ['gr']), AccessMode.VIEW)
assert not CheckAccessString('123=-;1234=dver', UserGroups('1234', []), AccessMode.ADD)
assert not CheckAccessString('123=-;1234=av', UserGroups('1234', []), AccessMode.DELETE)
assert not CheckAccessString('123=-;1234=dv', UserGroups('1234', []), AccessMode.EDIT)
assert not CheckAccessString('123=-;1234=av', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert not CheckAccessString('123=-;1234=a', UserGroups('1234', []), AccessMode.VIEW)
assert not CheckAccessString('123=-;gr1=vr', UserGroups('1234', ['gr']), AccessMode.ADD)
assert not CheckAccessString('123=-;gr1=aver', UserGroups('1234', ['gr']), AccessMode.DELETE)
assert not CheckAccessString('123=-;gr1=va', UserGroups('1234', ['gr']), AccessMode.EDIT)
assert not CheckAccessString('123=-;gr1=ea', UserGroups('1234', ['gr']), AccessMode.ACCEES_EDIT)
assert not CheckAccessString('123=-;gr1=ad', UserGroups('1234', ['gr']), AccessMode.VIEW)
assert CheckAccessString(f'123=-;{user_access_group_all}=a', UserGroups('1234', []), AccessMode.ADD)
assert CheckAccessString(f'123=-;{user_access_group_all}=d', UserGroups('1234', []), AccessMode.DELETE)
assert CheckAccessString(f'123=-;{user_access_group_all}=e', UserGroups('1234', []), AccessMode.EDIT)
assert CheckAccessString(f'123=-;{user_access_group_all}=r', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert CheckAccessString(f'123=-;{user_access_group_all}=v', UserGroups('1234', []), AccessMode.VIEW)
assert CheckAccessString(f'123=-;{user_access_group_all}=a', UserGroups('1234', ['gr1']), AccessMode.ADD)
assert CheckAccessString(f'123=-;{user_access_group_all}=d', UserGroups('1234', ['gr1']), AccessMode.DELETE)
assert CheckAccessString(f'123=-;{user_access_group_all}=e', UserGroups('1234', ['gr1']), AccessMode.EDIT)
assert CheckAccessString(f'123=-;{user_access_group_all}=r', UserGroups('1234', ['gr1']), AccessMode.ACCEES_EDIT)
assert CheckAccessString(f'123=-;{user_access_group_all}=v', UserGroups('1234', ['gr1']), AccessMode.VIEW)
assert CheckAccessString(f'123=-;{user_access_group_all}=daver', UserGroups('1234', []), AccessMode.ADD)
assert CheckAccessString(f'123=-;{user_access_group_all}=dav', UserGroups('1234', []), AccessMode.DELETE)
assert CheckAccessString(f'123=-;{user_access_group_all}=edv', UserGroups('1234', []), AccessMode.EDIT)
assert CheckAccessString(f'123=-;{user_access_group_all}=rav', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert CheckAccessString(f'123=-;{user_access_group_all}=va', UserGroups('1234', []), AccessMode.VIEW)
assert CheckAccessString(f'123=-;{user_access_group_all}=avr', UserGroups('1234', ['gr1']), AccessMode.ADD)
assert CheckAccessString(f'123=-;{user_access_group_all}=daver', UserGroups('1234', ['gr1']), AccessMode.DELETE)
assert CheckAccessString(f'123=-;{user_access_group_all}=eva', UserGroups('1234', ['gr1']), AccessMode.EDIT)
assert CheckAccessString(f'123=-;{user_access_group_all}=re', UserGroups('1234', ['gr1']), AccessMode.ACCEES_EDIT)
assert CheckAccessString(f'123=-;{user_access_group_all}=vad', UserGroups('1234', ['gr1']), AccessMode.VIEW)
assert not CheckAccessString(f'123=-;{user_access_group_all}=d', UserGroups('1234', []), AccessMode.ADD)
assert not CheckAccessString(f'123=-;{user_access_group_all}=a', UserGroups('1234', []), AccessMode.DELETE)
assert not CheckAccessString(f'123=-;{user_access_group_all}=r', UserGroups('1234', []), AccessMode.EDIT)
assert not CheckAccessString(f'123=-;{user_access_group_all}=v', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert not CheckAccessString(f'123=-;{user_access_group_all}=e', UserGroups('1234', []), AccessMode.VIEW)
assert not CheckAccessString(f'123=-;gr1=d;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.ADD)
assert not CheckAccessString(f'123=-;gr1=a;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.DELETE)
assert not CheckAccessString(f'123=-;gr1=v;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.EDIT)
assert not CheckAccessString(f'123=-;gr1=e;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.ACCEES_EDIT)
assert not CheckAccessString(f'123=-;gr1=r;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.VIEW)
assert not CheckAccessString(f'123=-;{user_access_group_all}=dver', UserGroups('1234', []), AccessMode.ADD)
assert not CheckAccessString(f'123=-;{user_access_group_all}=av', UserGroups('1234', []), AccessMode.DELETE)
assert not CheckAccessString(f'123=-;{user_access_group_all}=dv', UserGroups('1234', []), AccessMode.EDIT)
assert not CheckAccessString(f'123=-;{user_access_group_all}=av', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert not CheckAccessString(f'123=-;{user_access_group_all}=a', UserGroups('1234', []), AccessMode.VIEW)
assert not CheckAccessString(f'123=-;{user_access_group_all}=vr', UserGroups('1234', ['gr']), AccessMode.ADD)
assert not CheckAccessString(f'123=-;{user_access_group_all}=aver', UserGroups('1234', ['gr']), AccessMode.DELETE)
assert not CheckAccessString(f'123=-;{user_access_group_all}=va', UserGroups('1234', ['gr']), AccessMode.EDIT)
assert not CheckAccessString(f'123=-;{user_access_group_all}=ea', UserGroups('1234', ['gr']), AccessMode.ACCEES_EDIT)
assert not CheckAccessString(f'123=-;{user_access_group_all}=ad', UserGroups('1234', ['gr']), AccessMode.VIEW)
assert CheckAccess(roots, '1234=+', UserGroups('1234', []), am)
assert CheckAccess(roots, '1234=-', UserGroups('1234', []), am)
assert CheckAccess(roots, '1234=+;gr1=+', UserGroups('1234', ['gr1']), am)
assert CheckAccess(roots, '1234=-;gr1=+', UserGroups('1234', ['gr1']), am)
assert CheckAccess(roots, '1234=+', UserGroups('1234', []), am)
assert CheckAccess(roots, '1234=-', UserGroups('1234', []), am)
assert CheckAccess(roots, '1234=+;gr1=+', UserGroups('1234', ['gr']), am)
assert CheckAccess(roots, '1234=-;gr1=+', UserGroups('1234', ['gr']), am)
assert CheckAccess(roots, '1234=+;gr=+', UserGroups('1234', ['gr1']), am)
assert CheckAccess(roots, '1234=-;gr=+', UserGroups('1234', ['gr1']), am)
assert CheckAccess(roots, '123=+', UserGroups('1234', []), am)
assert CheckAccess(roots, '124=-', UserGroups('1234', []), am)
assert CheckAccess(roots, '134=+;gr1=+', UserGroups('1234', ['gr1']), am)
assert CheckAccess(roots, '134=-;gr1=+', UserGroups('1234', ['gr1']), am)
assert CheckAccess(roots, '124=+', UserGroups('1234', []), am)
assert CheckAccess(roots, '124=-', UserGroups('1234', []), am)
assert CheckAccess(roots, '134=+;gr1=+', UserGroups('1234', ['gr']), am)
assert CheckAccess(roots, '134=-;gr1=+', UserGroups('1234', ['gr']), am)
assert CheckAccess(roots, '124=+;gr=+', UserGroups('1234', ['gr1']), am)
assert CheckAccess(roots, '124=-;gr=+', UserGroups('1234', ['gr1']), am)
roots = ['12']
for am in AccessMode.ADD, AccessMode.DELETE, AccessMode.EDIT, AccessMode.VIEW, AccessMode.ACCEES_EDIT:
assert CheckAccess(roots, '1234=+', UserGroups('1234', []), am)
assert not CheckAccess(roots, '1234=-', UserGroups('1234', []), am)
assert CheckAccess(roots, '1234=+;gr1=+', UserGroups('1234', ['gr1']), am)
assert CheckAccess(roots, '1234=-;gr1=+', UserGroups('1234', ['gr1']), am)
assert not CheckAccess(roots, '1234=+', UserGroups('123', []), am)
assert not CheckAccess(roots, '1234=-', UserGroups('123', []), am)
assert not CheckAccess(roots, '1234=+;gr1=+', UserGroups('123', ['gr']), am)
assert not CheckAccess(roots, '1234=-;gr1=+', UserGroups('123', ['gr']), am)
assert not CheckAccess(roots, '1234=+;gr=+', UserGroups('123', ['gr1']), am)
assert not CheckAccess(roots, '1234=-;gr=+', UserGroups('123', ['gr1']), am)
assert CheckAccess(roots, '123=-;1234=a', UserGroups('1234', []), AccessMode.ADD)
assert CheckAccess(roots, '123=-;1234=d', UserGroups('1234', []), AccessMode.DELETE)
assert CheckAccess(roots, '123=-;1234=e', UserGroups('1234', []), AccessMode.EDIT)
assert CheckAccess(roots, '123=-;1234=r', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert CheckAccess(roots, '123=-;1234=v', UserGroups('1234', []), AccessMode.VIEW)
assert CheckAccess(roots, '123=-;gr1=a', UserGroups('1234', ['gr1']), AccessMode.ADD)
assert CheckAccess(roots, '123=-;gr1=d', UserGroups('1234', ['gr1']), AccessMode.DELETE)
assert CheckAccess(roots, '123=-;gr1=e', UserGroups('1234', ['gr1']), AccessMode.EDIT)
assert CheckAccess(roots, '123=-;gr1=r', UserGroups('1234', ['gr1']), AccessMode.ACCEES_EDIT)
assert CheckAccess(roots, '123=-;gr1=v', UserGroups('1234', ['gr1']), AccessMode.VIEW)
assert CheckAccess(roots, '123=-;1234=daver', UserGroups('1234', []), AccessMode.ADD)
assert CheckAccess(roots, '123=-;1234=dav', UserGroups('1234', []), AccessMode.DELETE)
assert CheckAccess(roots, '123=-;1234=edv', UserGroups('1234', []), AccessMode.EDIT)
assert CheckAccess(roots, '123=-;1234=rav', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert CheckAccess(roots, '123=-;1234=va', UserGroups('1234', []), AccessMode.VIEW)
assert CheckAccess(roots, '123=-;gr1=avr', UserGroups('1234', ['gr1']), AccessMode.ADD)
assert CheckAccess(roots, '123=-;gr1=daver', UserGroups('1234', ['gr1']), AccessMode.DELETE)
assert CheckAccess(roots, '123=-;gr1=eva', UserGroups('1234', ['gr1']), AccessMode.EDIT)
assert CheckAccess(roots, '123=-;gr1=re', UserGroups('1234', ['gr1']), AccessMode.ACCEES_EDIT)
assert CheckAccess(roots, '123=-;gr1=vad', UserGroups('1234', ['gr1']), AccessMode.VIEW)
assert not CheckAccess(roots, '123=-;1234=d', UserGroups('1234', []), AccessMode.ADD)
assert not CheckAccess(roots, '123=-;1234=a', UserGroups('1234', []), AccessMode.DELETE)
assert not CheckAccess(roots, '123=-;1234=r', UserGroups('1234', []), AccessMode.EDIT)
assert not CheckAccess(roots, '123=-;1234=v', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert not CheckAccess(roots, '123=-;1234=e', UserGroups('1234', []), AccessMode.VIEW)
assert not CheckAccess(roots, '123=-;gr1=d', UserGroups('1234', ['gr']), AccessMode.ADD)
assert not CheckAccess(roots, '123=-;gr1=a', UserGroups('1234', ['gr']), AccessMode.DELETE)
assert not CheckAccess(roots, '123=-;gr1=v', UserGroups('1234', ['gr']), AccessMode.EDIT)
assert not CheckAccess(roots, '123=-;gr1=e', UserGroups('1234', ['gr']), AccessMode.ACCEES_EDIT)
assert not CheckAccess(roots, '123=-;gr1=r', UserGroups('1234', ['gr']), AccessMode.VIEW)
assert not CheckAccess(roots, '123=-;1234=dver', UserGroups('1234', []), AccessMode.ADD)
assert not CheckAccess(roots, '123=-;1234=av', UserGroups('1234', []), AccessMode.DELETE)
assert not CheckAccess(roots, '123=-;1234=dv', UserGroups('1234', []), AccessMode.EDIT)
assert not CheckAccess(roots, '123=-;1234=av', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert not CheckAccess(roots, '123=-;1234=a', UserGroups('1234', []), AccessMode.VIEW)
assert not CheckAccess(roots, '123=-;gr1=vr', UserGroups('1234', ['gr']), AccessMode.ADD)
assert not CheckAccess(roots, '123=-;gr1=aver', UserGroups('1234', ['gr']), AccessMode.DELETE)
assert not CheckAccess(roots, '123=-;gr1=va', UserGroups('1234', ['gr']), AccessMode.EDIT)
assert not CheckAccess(roots, '123=-;gr1=ea', UserGroups('1234', ['gr']), AccessMode.ACCEES_EDIT)
assert not CheckAccess(roots, '123=-;gr1=ad', UserGroups('1234', ['gr']), AccessMode.VIEW)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=a', UserGroups('1234', []), AccessMode.ADD)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=d', UserGroups('1234', []), AccessMode.DELETE)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=e', UserGroups('1234', []), AccessMode.EDIT)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=r', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=v', UserGroups('1234', []), AccessMode.VIEW)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=a', UserGroups('1234', ['gr1']), AccessMode.ADD)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=d', UserGroups('1234', ['gr1']), AccessMode.DELETE)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=e', UserGroups('1234', ['gr1']), AccessMode.EDIT)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=r', UserGroups('1234', ['gr1']), AccessMode.ACCEES_EDIT)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=v', UserGroups('1234', ['gr1']), AccessMode.VIEW)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=daver', UserGroups('1234', []), AccessMode.ADD)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=dav', UserGroups('1234', []), AccessMode.DELETE)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=edv', UserGroups('1234', []), AccessMode.EDIT)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=rav', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=va', UserGroups('1234', []), AccessMode.VIEW)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=avr', UserGroups('1234', ['gr1']), AccessMode.ADD)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=daver', UserGroups('1234', ['gr1']), AccessMode.DELETE)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=eva', UserGroups('1234', ['gr1']), AccessMode.EDIT)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=re', UserGroups('1234', ['gr1']), AccessMode.ACCEES_EDIT)
assert CheckAccess(roots, f'123=-;{user_access_group_all}=vad', UserGroups('1234', ['gr1']), AccessMode.VIEW)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=d', UserGroups('1234', []), AccessMode.ADD)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=a', UserGroups('1234', []), AccessMode.DELETE)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=r', UserGroups('1234', []), AccessMode.EDIT)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=v', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=e', UserGroups('1234', []), AccessMode.VIEW)
assert not CheckAccess(roots, f'123=-;gr1=d;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.ADD)
assert not CheckAccess(roots, f'123=-;gr1=a;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.DELETE)
assert not CheckAccess(roots, f'123=-;gr1=v;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.EDIT)
assert not CheckAccess(roots, f'123=-;gr1=e;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.ACCEES_EDIT)
assert not CheckAccess(roots, f'123=-;gr1=r;{user_access_group_all}=-', UserGroups('1234', ['gr']), AccessMode.VIEW)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=dver', UserGroups('1234', []), AccessMode.ADD)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=av', UserGroups('1234', []), AccessMode.DELETE)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=dv', UserGroups('1234', []), AccessMode.EDIT)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=av', UserGroups('1234', []), AccessMode.ACCEES_EDIT)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=a', UserGroups('1234', []), AccessMode.VIEW)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=vr', UserGroups('1234', ['gr']), AccessMode.ADD)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=aver', UserGroups('1234', ['gr']), AccessMode.DELETE)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=va', UserGroups('1234', ['gr']), AccessMode.EDIT)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=ea', UserGroups('1234', ['gr']), AccessMode.ACCEES_EDIT)
assert not CheckAccess(roots, f'123=-;{user_access_group_all}=ad', UserGroups('1234', ['gr']), AccessMode.VIEW)

56
bot_sys/user_messages.py

@ -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)

122
main.py

@ -4,45 +4,117 @@
log_start_message = 'Бот успешно запущен!'
import os
from aiogram import Bot, types
from aiogram.utils import executor
from aiogram.dispatcher import Dispatcher
from aiogram.contrib.fsm_storage.memory import MemoryStorage
import sqlite3
from bot_sys import config, log, bot_bd, user_access, user_messages
from bot_modules import profile, start, projects, groups, access, backup, tasks, needs, comments, messages, languages
storage = MemoryStorage()
bot = Bot(token = config.GetTelegramBotApiToken(), parse_mode = types.ParseMode.HTML)
dp = Dispatcher(bot, storage = storage)
# Первичная инициализация модулей. Все модули должны быть прописаны в списке modules
modules = [tasks, access, profile, start, projects, groups, backup, needs, comments, messages, languages]
init_bd_cmd = []
from bot_sys import config, log, aiogram_bot, bot_messages, bd_table, user_access
from bot_modules import mod_agregator, start, profile, backup, groups, access, projects, tasks, needs, comments, languages, messages, buttons
bd_file_name = 'bot.db'
log_file_name = 'log.txt'
g_Log = log.Log(log_file_name)
g_Bot = aiogram_bot.AiogramBot(config.GetTelegramBotApiToken(), bd_file_name, config.GetRootIDs(), g_Log)
default_language = 'ru'
g_BotMessages = bot_messages.BotMessages(default_language)
g_BotButtons = bot_messages.BotMessages(default_language)
g_ModuleAgregator = mod_agregator.ModuleAgregator()
mod_start_name = start.module_name
mod_tasks_name = tasks.module_name
mod_needs_name = needs.module_name
mod_comments_name = comments.module_name
mod_projects_name = projects.module_name
mod_languages_name = languages.module_name
mod_messages_name = messages.module_name
mod_buttons_name = buttons.module_name
start_mod_list = [mod_start_name]
mod_access = access.ModuleAccess(start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_access)
mod_groups = groups.ModuleGroups(start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_groups)
mod_profile = profile.ModuleProfile(start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_profile)
mod_backup = backup.ModuleBackup(start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_backup)
start_mod_name_list = [mod_start_name, mod_tasks_name, mod_needs_name, mod_comments_name]
mod_project = projects.ModuleProjects(None, mod_tasks_name, start_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_project)
start_mod_name_list = [mod_start_name]#, mod_projects_name, mod_needs_name, mod_comments_name]
mod_tasks = tasks.ModuleTasks(mod_projects_name, mod_needs_name, start_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_tasks)
start_mod_name_list = [mod_start_name]#, mod_projects_name, mod_tasks_name, mod_comments_name]
mod_needs= needs.ModuleNeeds(mod_tasks_name, mod_comments_name, start_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_needs)
start_mod_name_list = [mod_start_name]#, mod_projects_name, mod_tasks_name, mod_needs_name]
mod_comments= comments.ModuleComments(mod_needs_name, None, start_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_comments)
start_mod_name_list = [mod_start_name, mod_messages_name, mod_buttons_name]
mod_languages = languages.ModuleLanguages(None, mod_messages_name, start_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_languages)
start_mod_name_list = [mod_start_name]
mod_messages = messages.ModuleMessages(mod_languages_name, None, start_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_messages)
start_mod_name_list = [mod_start_name]
mod_buttons = buttons.ModuleButtons(mod_languages_name, None, start_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_buttons)
start_mod_name_list = [
mod_profile.GetName(),
mod_backup.GetName(),
mod_groups.GetName(),
mod_access.GetName(),
mod_project.GetName(),
mod_languages.GetName(),
]
mod_start = start.ModuleStart(start_mod_name_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_Log)
g_ModuleAgregator.AddModule(mod_start)
# Первичная инициализация модулей.
modules = g_ModuleAgregator.GetModList()
init_bd_cmds = []
for m in modules:
c = m.GetInitBDCommands()
if not c is None:
init_bd_cmd += c
init_bd_cmds += c
# Первичная инициализация базы данных
bot_bd.BDExecute(init_bd_cmd)
for c in init_bd_cmds:
g_Bot.SQLRequest(c, commit = True)
user_messages.UpdateSignal(log.GetTimeNow())
g_BotMessages.UpdateSignal(g_Log.GetTimeNow())
g_BotButtons.UpdateSignal(g_Log.GetTimeNow())
languages.FlushLanguages()
messages.FlushMessages()
mod_languages.FlushLanguages()
mod_messages.FlushMessages()
mod_buttons.FlushMessages()
for m in modules:
m.RegisterHandlers(dp)
m.RegisterHandlers()
# Юнит тесты модулей и файлов
test_mods = [user_access]
test_mods = [user_access, bd_table]
for m in test_mods:
m.Test()
if __name__ == '__main__':
# os.system('clear')
# os.system('cls')
log.Success(log_start_message)
g_Log.Success(log_start_message)
executor.start_polling(dp)
g_Bot.StartPolling()

51
template/bd_item.py

@ -4,8 +4,8 @@
# Работа с элементом в БД
from enum import Enum
from bot_sys import user_access, bot_bd, keyboard, log
from bot_modules import groups, access
from bot_sys import user_access, bot_bd, keyboard, bot_messages
from bot_modules import groups_utils, access_utils
from template import simple_message
from aiogram import types
@ -20,7 +20,7 @@ canсel_button_name = "🚫 Отменить"
def HashPrefix(a_Str):
# callback data в сообщении имеет ограниченную длину, поэтому сокращаем префикс
#log.Info(f'HashPrefix {md5(a_Str)[0:8]}: - {a_Str}')
#a_Bot.GetLog().Info(f'HashPrefix {md5(a_Str)[0:8]}: - {a_Str}')
return f'{md5(a_Str)[0:8]}:'
class FieldType(Enum):
@ -31,7 +31,10 @@ def GetCheckForPrefixFunc(a_Prefix):
return lambda x: x.data.startswith(a_Prefix)
def GetCheckForTextFunc(a_Text):
return lambda x: x.text == a_Text
return lambda x: x.text == str(a_Text)
def GetCheckForCommandsFunc(a_Commands):
return lambda x: x.commands == a_Commands
def GetKeyDataFromCallbackMessage(a_Message, a_Prefix):
key_item_id = None
@ -39,60 +42,60 @@ def GetKeyDataFromCallbackMessage(a_Message, a_Prefix):
key_item_id = str(a_Message.data).replace(a_Prefix, '')
return key_item_id
def GetCancelKeyboardButtonsTemplate(a_AccessFunc, a_AccessMode):
def GetCancelKeyboardButtonsTemplate(a_Bot, a_AccessFunc, a_AccessMode):
def GetCancelKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(canсel_button_name, a_AccessMode, a_AccessFunc()),
]
return keyboard.MakeKeyboard(cur_buttons, a_UserGroups)
return keyboard.MakeButtons(a_Bot, cur_buttons, a_UserGroups)
return GetCancelKeyboardButtons
def GetSkipAndCancelKeyboardButtonsTemplate(a_AccessFunc, a_AccessMode):
def GetSkipAndCancelKeyboardButtonsTemplate(a_Bot, a_AccessFunc, a_AccessMode):
def GetSkipAndCancelKeyboardButtons(a_Message, a_UserGroups):
cur_buttons = [
keyboard.ButtonWithAccess(skip_button_name, a_AccessMode, a_AccessFunc()),
keyboard.ButtonWithAccess(canсel_button_name, a_AccessMode, a_AccessFunc()),
]
return keyboard.MakeKeyboard(cur_buttons, a_UserGroups)
return keyboard.MakeButtons(a_Bot, cur_buttons, a_UserGroups)
return GetSkipAndCancelKeyboardButtons
def GetAllItemsTemplate(a_TableName):
def GetAllItemsTemplate(a_Bot, a_TableName):
def GetAllItems():
return bot_bd.SelectBDTemplate(a_TableName)()
return bot_bd.SelectBDTemplate(a_Bot, a_TableName)()
return GetAllItems
def GetBDItemsTemplate(a_TableName : str, a_KeyName : str):
def GetBDItemsTemplate(a_Bot, a_TableName : str, a_KeyName : str):
def GetBDItem(a_KeyValue):
return bot_bd.SQLRequestToBD(f'SELECT * FROM {a_TableName} WHERE {a_KeyName} = ?', param = ([a_KeyValue]))
return a_Bot.SQLRequest(f'SELECT * FROM {a_TableName} WHERE {a_KeyName} = ?', param = ([a_KeyValue]))
return GetBDItem
def DeleteBDItemInTableTemplate(a_TableName : str, a_KeyName : str):
def DeleteBDItemInTableTemplate(a_Bot, a_TableName : str, a_KeyName : str):
def DeleteBDItem(a_KeyValue):
return bot_bd.SQLRequestToBD(f'DELETE FROM {a_TableName} WHERE {a_KeyName} = ?', commit = True, return_error = True, param = ([a_KeyValue]))
return a_Bot.SQLRequest(f'DELETE FROM {a_TableName} WHERE {a_KeyName} = ?', commit = True, return_error = True, param = ([a_KeyValue]))
return DeleteBDItem
def EditBDItemInTableTemplate(a_TableName : str, a_KeyName : str, a_FieldName : str):
def EditBDItemInTableTemplate(a_Bot, a_TableName : str, a_KeyName : str, a_FieldName : str):
def EditBDItemInTable(a_KeyValue, a_FieldValue):
return bot_bd.SQLRequestToBD(f'UPDATE {a_TableName} SET {a_FieldName}=? WHERE {a_KeyName} = ?', commit = True, return_error = True, param = ([a_FieldValue, a_KeyValue]))
return a_Bot.SQLRequest(f'UPDATE {a_TableName} SET {a_FieldName}=? WHERE {a_KeyName} = ?', commit = True, return_error = True, param = ([a_FieldValue, a_KeyValue]))
return EditBDItemInTable
def CheckAccessBDItemTemplate(a_TableName, a_KeyName, a_KeyValue, a_WorkFunc, a_AccessMode : user_access.AccessMode):
def CheckAccessBDItemTemplate(a_Bot, a_TableName, a_KeyName, a_KeyValue, a_WorkFunc, a_AccessMode : user_access.AccessMode):
async def CheckAccessBDItem(a_CallbackQuery : types.CallbackQuery):
user_id = str(a_CallbackQuery.from_user.id)
user_groups = groups.GetUserGroupData(user_id)
user_groups = groups_utils.GetUserGroupData(a_Bot, user_id)
item_id = a_KeyValue
item = GetBDItemsTemplate(a_TableName, a_KeyName)(item_id)
item = GetBDItemsTemplate(a_Bot, a_TableName, a_KeyName)(item_id)
if len(item) < 1:
msg = item_not_found.replace('{item_id}', str(item_id)).replace('{a_TableName}', a_TableName)
log.Error(msg)
return simple_message.WorkFuncResult(msg), None
a_Bot.GetLog().Error(msg)
return simple_message.WorkFuncResult(bot_messages.MakeBotMessage(msg)), None
result_work_func = await a_WorkFunc(a_CallbackQuery, item[0])
if result_work_func is None or result_work_func.string_message is None:
if result_work_func is None or result_work_func.m_BotMessage is None:
return result_work_func, result_work_func
if not result_work_func.item_access is None and not user_access.CheckAccessString(result_work_func.item_access, user_groups, a_AccessMode):
return simple_message.WorkFuncResult(access.access_denied_message), None
if not result_work_func.item_access is None and not user_access.CheckAccess(a_Bot.GetRootIDs(), result_work_func.item_access, user_groups, a_AccessMode):
return simple_message.WorkFuncResult(bot_messages.MakeBotMessage(access_utils.access_denied_message)), None
return None, result_work_func
return CheckAccessBDItem

78
template/bd_item_add.py

@ -3,23 +3,18 @@
# Добавление элемента в БД
from bot_sys import user_access, bot_bd, log
from bot_modules import access, groups
from bot_sys import user_access, bot_bd, bot_messages
from bot_modules import access_utils, groups_utils
from template import simple_message, bd_item_select, bd_item
from aiogram import types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
cancel_message = '''
🚫 Добавление отменено
'''
def StartAddBDItemTemplate(a_FSM, a_FSMStart, a_MessageFunc, a_ParentTableName, a_ParentKeyFieldName, a_Prefix, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, access_mode = user_access.AccessMode.ADD):
async def StartAddBDItem(a_CallbackQuery : types.CallbackQuery, state : FSMContext):
def StartAddBDItemTemplate(a_Bot, a_FSM, a_FSMStart, a_MessageFunc, a_ParentTableName, a_ParentKeyFieldName, a_Prefix, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, access_mode = user_access.AccessMode.ADD):
async def StartAddBDItem(a_CallbackQuery, state):
user_id = str(a_CallbackQuery.from_user.id)
user_groups = groups.GetUserGroupData(user_id)
user_groups = groups_utils.GetUserGroupData(a_Bot, user_id)
parent_id = bd_item.GetKeyDataFromCallbackMessage(a_CallbackQuery, a_Prefix)
res_of_work_func = None
check = None
@ -30,7 +25,7 @@ def StartAddBDItemTemplate(a_FSM, a_FSMStart, a_MessageFunc, a_ParentTableName,
item_data[a_ParentKeyFieldName] = parent_id
if parent_id:
check, res_of_work_func = await bd_item.CheckAccessBDItemTemplate(a_ParentTableName, a_ParentKeyFieldName, parent_id, a_MessageFunc, access_mode)(a_CallbackQuery)
check, res_of_work_func = await bd_item.CheckAccessBDItemTemplate(a_Bot, a_ParentTableName, a_ParentKeyFieldName, parent_id, a_MessageFunc, access_mode)(a_CallbackQuery)
else:
res_of_work_func = await a_MessageFunc(a_CallbackQuery, None)
@ -39,36 +34,36 @@ def StartAddBDItemTemplate(a_FSM, a_FSMStart, a_MessageFunc, a_ParentTableName,
check.keyboard_func = a_FinishButtonFunc
return check
return res_of_work_func
return simple_message.SimpleMessageTemplate(StartAddBDItem, a_ButtonFunc, a_AccessFunc, access_mode)
return simple_message.SimpleMessageTemplate(a_Bot, StartAddBDItem, a_ButtonFunc, None, a_AccessFunc, access_mode)
def FinishAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.ADD, field_type = bd_item.FieldType.text):
return FinishOrNextAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_ButtonFunc, True, access_mode = access_mode, field_type = field_type)
def FinishAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.ADD, field_type = bd_item.FieldType.text):
return FinishOrNextAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_ButtonFunc, True, access_mode = access_mode, field_type = field_type)
def NextAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, access_mode = user_access.AccessMode.ADD, field_type = bd_item.FieldType.text):
return FinishOrNextAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, False, access_mode = access_mode, field_type = field_type)
def NextAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, access_mode = user_access.AccessMode.ADD, field_type = bd_item.FieldType.text):
return FinishOrNextAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, False, access_mode = access_mode, field_type = field_type)
def FinishOrNextAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, a_Finish, access_mode = user_access.AccessMode.ADD, field_type = bd_item.FieldType.text):
async def FinishAddBDItem(a_Message : types.CallbackQuery, state : FSMContext):
def FinishOrNextAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, a_Finish, access_mode = user_access.AccessMode.ADD, field_type = bd_item.FieldType.text):
async def FinishAddBDItem(a_Message, state):
state_func = None
if a_Finish:
state_func = state.finish
else:
state_func = a_FSM.next
user_id = str(a_Message.from_user.id)
user_groups = groups.GetUserGroupData(user_id)
user_groups = groups_utils.GetUserGroupData(a_Bot, user_id)
error = None
res_of_work_func = None
check = None
async with state.proxy() as item_data:
if a_Message.text == bd_item.canсel_button_name:
await state.finish()
return simple_message.WorkFuncResult(cancel_message, keyboard_func = a_FinishButtonFunc)
return simple_message.WorkFuncResult(bot_messages.MakeBotMessage(cancel_message), keyboard_func = a_FinishButtonFunc)
parent_id = None
if a_ParentKeyFieldName:
parent_id = item_data[a_ParentKeyFieldName]
if parent_id:
check, res_of_work_func = await bd_item.CheckAccessBDItemTemplate(a_ParentTableName, a_ParentKeyFieldName, parent_id, a_MessageFunc, access_mode)(a_Message)
check, res_of_work_func = await bd_item.CheckAccessBDItemTemplate(a_Bot, a_ParentTableName, a_ParentKeyFieldName, parent_id, a_MessageFunc, access_mode)(a_Message)
else:
res_of_work_func = await a_MessageFunc(a_Message, None)
@ -83,7 +78,7 @@ def FinishOrNextAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_P
else:
if a_Message.photo == None or len(a_Message.photo) == 0:
await state.finish()
return simple_message.WorkFuncResult(error_photo_type_message, keyboard_func = a_FinishButtonFunc)
return simple_message.WorkFuncResult(bot_messages.MakeBotMessage(error_photo_type_message), keyboard_func = a_FinishButtonFunc)
field_value = a_Message.photo[0].file_id
else:
field_value = a_Message.text
@ -92,31 +87,32 @@ def FinishOrNextAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_P
res, error = a_AddBDItemFunc(item_data, user_id)
await state_func()
if error:
return simple_message.WorkFuncResult(error)
return simple_message.WorkFuncResult(bot_messages.MakeBotMessage(error))
return res_of_work_func
return simple_message.SimpleMessageTemplate(FinishAddBDItem, a_ButtonFunc, a_AccessFunc, access_mode)
return simple_message.SimpleMessageTemplate(a_Bot, FinishAddBDItem, a_ButtonFunc, None, a_AccessFunc, access_mode)
def AddBDItem3RegisterHandlers(dp, a_StartCheckFunc, a_FSM, a_FSMName, a_FSMDesc, a_FSMPhoto, a_AddBDItemFunc, a_AddNameMessageFunc, a_AddDescMessageFunc, a_AddPhotoMessageFunc, a_FinishMessageFunc, a_ParentPrefix, a_ParentTableName : str, a_ParentKeyFieldName, a_NameField, a_DescField, a_PhotoField, a_GetButtonNameAndKeyValueAndAccessFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.ADD):
keyboard_cancel = bd_item.GetCancelKeyboardButtonsTemplate(a_AccessFunc, access_mode)
keyboard_skip_and_cancel = bd_item.GetSkipAndCancelKeyboardButtonsTemplate(a_AccessFunc, access_mode)
reg_func = dp.register_message_handler
def AddBDItem3RegisterHandlers(a_Bot, a_StartCheckFunc, a_FSM, a_FSMName, a_FSMDesc, a_FSMPhoto, a_AddBDItemFunc, a_AddNameMessageFunc, a_AddDescMessageFunc, a_AddPhotoMessageFunc, a_FinishMessageFunc, a_ParentPrefix, a_ParentTableName : str, a_ParentKeyFieldName, a_NameField, a_DescField, a_PhotoField, a_GetButtonNameAndKeyValueAndAccessFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.ADD):
keyboard_cancel = bd_item.GetCancelKeyboardButtonsTemplate(a_Bot, a_AccessFunc, access_mode)
keyboard_skip_and_cancel = bd_item.GetSkipAndCancelKeyboardButtonsTemplate(a_Bot, a_AccessFunc, access_mode)
reg_func = a_Bot.RegisterMessageHandler
if a_ParentTableName:
reg_func = dp.register_callback_query_handler
reg_func(StartAddBDItemTemplate(a_FSM, a_FSMName, a_AddNameMessageFunc, a_ParentTableName, a_ParentKeyFieldName, a_ParentPrefix, a_AccessFunc, keyboard_cancel, a_ButtonFunc, access_mode), a_StartCheckFunc)
reg_func = a_Bot.RegisterCallbackHandler
reg_func(StartAddBDItemTemplate(a_Bot, a_FSM, a_FSMName, a_AddNameMessageFunc, a_ParentTableName, a_ParentKeyFieldName, a_ParentPrefix, a_AccessFunc, keyboard_cancel, a_ButtonFunc, access_mode), a_StartCheckFunc)
dp.register_message_handler(NextAddBDItemTemplate(a_FSM, None, a_ParentTableName, a_ParentKeyFieldName, a_NameField, a_AddDescMessageFunc, a_AccessFunc, keyboard_cancel, a_ButtonFunc, access_mode, field_type = bd_item.FieldType.text), state = a_FSMName)
dp.register_message_handler(NextAddBDItemTemplate(a_FSM, None, a_ParentTableName, a_ParentKeyFieldName, a_DescField, a_AddPhotoMessageFunc, a_AccessFunc, keyboard_skip_and_cancel, a_ButtonFunc, access_mode, field_type = bd_item.FieldType.text), state = a_FSMDesc)
dp.register_message_handler(FinishAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_PhotoField, a_FinishMessageFunc, a_AccessFunc, a_ButtonFunc, access_mode, field_type = bd_item.FieldType.photo), content_types = ['photo', 'text'], state = a_FSMPhoto)
# TODO: Сделать возможность не указывать все поля. пусть a_FSMName и a_NameField например могут быть пустыми. Возможно лучше вообще передавать список полей и их fsm
a_Bot.RegisterMessageHandler(NextAddBDItemTemplate(a_Bot, a_FSM, None, a_ParentTableName, a_ParentKeyFieldName, a_NameField, a_AddDescMessageFunc, a_AccessFunc, keyboard_cancel, a_ButtonFunc, access_mode, field_type = bd_item.FieldType.text), state = a_FSMName)
a_Bot.RegisterMessageHandler(NextAddBDItemTemplate(a_Bot, a_FSM, None, a_ParentTableName, a_ParentKeyFieldName, a_DescField, a_AddPhotoMessageFunc, a_AccessFunc, keyboard_skip_and_cancel, a_ButtonFunc, access_mode, field_type = bd_item.FieldType.text), state = a_FSMDesc)
a_Bot.RegisterMessageHandler(FinishAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_PhotoField, a_FinishMessageFunc, a_AccessFunc, a_ButtonFunc, access_mode, field_type = bd_item.FieldType.photo), content_types = ['photo', 'text'], state = a_FSMPhoto)
def AddBDItem1RegisterHandlers(dp, a_StartCheckFunc, a_FSM, a_AddBDItemFunc, a_AddMessageFunc, a_FinishMessageFunc, a_ParentPrefix, a_ParentTableName : str, a_ParentKeyFieldName, a_FieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_AccessFunc, a_ButtonFunc, a_FieldType, access_mode = user_access.AccessMode.ADD):
keyboard_cancel = bd_item.GetCancelKeyboardButtonsTemplate(a_AccessFunc, access_mode)
reg_func = dp.register_message_handler
def AddBDItem1RegisterHandlers(a_Bot, a_StartCheckFunc, a_FSM, a_AddBDItemFunc, a_AddMessageFunc, a_FinishMessageFunc, a_ParentPrefix, a_ParentTableName : str, a_ParentKeyFieldName, a_FieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_AccessFunc, a_ButtonFunc, a_FieldType, access_mode = user_access.AccessMode.ADD):
keyboard_cancel = bd_item.GetCancelKeyboardButtonsTemplate(a_Bot, a_AccessFunc, access_mode)
reg_func = a_Bot.RegisterMessageHandler
if a_ParentTableName:
reg_func = dp.register_callback_query_handler
reg_func(StartAddBDItemTemplate(a_FSM, a_FSM.bd_item, a_AddMessageFunc, a_ParentTableName, a_ParentKeyFieldName, a_ParentPrefix, a_AccessFunc, keyboard_cancel, a_ButtonFunc, access_mode), a_StartCheckFunc)
finish_handler = FinishAddBDItemTemplate(a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_FinishMessageFunc, a_AccessFunc, a_ButtonFunc, access_mode, field_type = a_FieldType)
reg_func = a_Bot.RegisterCallbackHandler
reg_func(StartAddBDItemTemplate(a_Bot, a_FSM, a_FSM.bd_item, a_AddMessageFunc, a_ParentTableName, a_ParentKeyFieldName, a_ParentPrefix, a_AccessFunc, keyboard_cancel, a_ButtonFunc, access_mode), a_StartCheckFunc)
finish_handler = FinishAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, a_FieldName, a_FinishMessageFunc, a_AccessFunc, a_ButtonFunc, access_mode, field_type = a_FieldType)
if a_FieldType == bd_item.FieldType.photo:
dp.register_message_handler(finish_handler, content_types = ['photo', 'text'], state = a_FSM.bd_item)
a_Bot.RegisterMessageHandler(finish_handler, content_types = ['photo', 'text'], state = a_FSM.bd_item)
else:
dp.register_message_handler(finish_handler, state = a_FSM.bd_item)
a_Bot.RegisterMessageHandler(finish_handler, state = a_FSM.bd_item)

31
template/bd_item_delete.py

@ -4,40 +4,41 @@
# удаление элемента в БД
from bot_sys import user_access, bot_bd, keyboard
from bot_modules import access, groups
from bot_modules import access_utils, groups_utils
from template import simple_message, bd_item_select, bd_item
from aiogram import types
def DeleteBDItemTemplate(a_TableName, a_KeyName, a_PreDeleteWorkFunc, a_PostDeleteWorkFunc, a_Prefix, a_AccessFunc, a_ButtonFunc, delete = True, access_mode = user_access.AccessMode.DELETE):
async def DeleteBDItem(a_CallbackQuery : types.CallbackQuery, state = None):
def DeleteBDItemTemplate(a_Bot, a_TableName, a_KeyName, a_PreDeleteWorkFunc, a_PostDeleteWorkFunc, a_Prefix, a_AccessFunc, a_ButtonFunc, delete = True, access_mode = user_access.AccessMode.DELETE):
async def DeleteBDItem(a_CallbackQuery, state = None):
user_id = str(a_CallbackQuery.from_user.id)
user_groups = groups.GetUserGroupData(user_id)
user_groups = groups_utils.GetUserGroupData(a_Bot, user_id)
item_id = str(a_CallbackQuery.data).replace(a_Prefix, '')
check, res_of_pre_del = await bd_item.CheckAccessBDItemTemplate(a_TableName, a_KeyName, item_id, a_PreDeleteWorkFunc, access_mode)(a_CallbackQuery)
check, res_of_pre_del = await bd_item.CheckAccessBDItemTemplate(a_Bot, a_TableName, a_KeyName, item_id, a_PreDeleteWorkFunc, access_mode)(a_CallbackQuery)
if not check is None:
return check
if not delete:
return res_of_pre_del
result, error = bd_item.DeleteBDItemInTableTemplate(a_TableName, a_KeyName)(item_id)
result, error = bd_item.DeleteBDItemInTableTemplate(a_Bot, a_TableName, a_KeyName)(item_id)
if not error is None:
msg = error
log.Error(error)
a_Bot.GetLog().Error(error)
return simple_message.WorkFuncResult(error)
return await a_PostDeleteWorkFunc(a_CallbackQuery, item_id)
return simple_message.SimpleMessageTemplate(DeleteBDItem, a_ButtonFunc, a_AccessFunc, access_mode)
return simple_message.SimpleMessageTemplate(a_Bot, DeleteBDItem, a_ButtonFunc, None, a_AccessFunc, access_mode)
def DeleteBDItemRegisterHandlers(dp, a_PrevPrefix, a_StartCheckFunc, a_TableName : str, a_KeyName, a_ParentIDFieldName,a_PreDeleteWorkFunc, a_PostDeleteWorkFunc, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.DELETE):
reg_func = dp.register_message_handler
def SelectAndDeleteBDItemRegisterHandlers(a_Bot, a_PrevPrefix, a_StartCheckFunc, a_TableName : str, a_KeyName, a_ParentIDFieldName,a_PreDeleteWorkFunc, a_PostDeleteWorkFunc, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.DELETE):
reg_func = a_Bot.RegisterMessageHandler
if a_ParentIDFieldName:
reg_func = dp.register_callback_query_handler
reg_func = a_Bot.RegisterCallbackHandler
a_Prefix = bd_item.HashPrefix(f'delete_{a_TableName}_{a_KeyName}:')
sel_handler = bd_item_select.SelectDBItemTemplate(a_TableName, a_ParentIDFieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_PrevPrefix, a_Prefix, access_mode)
sel_handler = bd_item_select.SelectDBItemTemplate(a_Bot, a_TableName, a_ParentIDFieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_PrevPrefix, a_Prefix, access_mode)
reg_func(sel_handler, a_StartCheckFunc)
dp.register_callback_query_handler(DeleteBDItemTemplate(a_TableName, a_KeyName, a_PreDeleteWorkFunc, a_PostDeleteWorkFunc, a_Prefix, a_AccessFunc, a_ButtonFunc, access_mode), bd_item.GetCheckForPrefixFunc(a_Prefix))
a_Bot.RegisterCallbackHandler(DeleteBDItemTemplate(a_Bot, a_TableName, a_KeyName, a_PreDeleteWorkFunc, a_PostDeleteWorkFunc, a_Prefix, a_AccessFunc, a_ButtonFunc, access_mode), bd_item.GetCheckForPrefixFunc(a_Prefix))
def DeleteBDItemRegisterHandlers(a_Bot, a_PrevPrefix, a_TableName : str, a_KeyName, a_PreDeleteWorkFunc, a_PostDeleteWorkFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.DELETE):
a_Bot.RegisterCallbackHandler(DeleteBDItemTemplate(a_Bot, a_TableName, a_KeyName, a_PreDeleteWorkFunc, a_PostDeleteWorkFunc, a_PrevPrefix, a_AccessFunc, a_ButtonFunc, access_mode), bd_item.GetCheckForPrefixFunc(a_PrevPrefix))

40
template/bd_item_edit.py

@ -3,14 +3,10 @@
# Редактирование элемента в БД
from bot_sys import user_access, bot_bd, log
from bot_modules import access, groups
from bot_sys import user_access, bot_bd
from bot_modules import access_utils, groups_utils
from template import simple_message, bd_item_select, bd_item, bd_item_add
from aiogram import types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
cancel_message = '''
🚫 Редактирование отменено
'''
@ -19,33 +15,35 @@ error_photo_type_message = '''
🚫 Фотографий не найдено
'''
def StartEditBDItemTemplate(a_FSM, a_MessageFunc, a_TableName, a_KeyName, a_Prefix, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, access_mode = user_access.AccessMode.EDIT):
return bd_item_add.StartAddBDItemTemplate(a_FSM, a_FSM.item_field, a_MessageFunc, a_TableName, a_KeyName, a_Prefix, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, access_mode = access_mode)
def StartEditBDItemTemplate(a_Bot, a_FSM, a_MessageFunc, a_TableName, a_KeyName, a_Prefix, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, access_mode = user_access.AccessMode.EDIT):
return bd_item_add.StartAddBDItemTemplate(a_Bot, a_FSM, a_FSM.item_field, a_MessageFunc, a_TableName, a_KeyName, a_Prefix, a_AccessFunc, a_ButtonFunc, a_FinishButtonFunc, access_mode = access_mode)
def FinishEditBDItemTemplate(a_FSM, a_TableName, a_KeyName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.EDIT, field_type = bd_item.FieldType.text):
def FinishEditBDItemTemplate(a_Bot, a_FSM, a_TableName, a_KeyName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, a_OnChangeFunc, access_mode = user_access.AccessMode.EDIT, field_type = bd_item.FieldType.text):
def EditBDItemFunc(a_ItemData, a_UserID):
item_id = a_ItemData[a_KeyName]
field_value = a_ItemData[a_FieldName]
res, error = bd_item.EditBDItemInTableTemplate(a_TableName, a_KeyName, a_FieldName)(item_id, field_value)
res, error = bd_item.EditBDItemInTableTemplate(a_Bot, a_TableName, a_KeyName, a_FieldName)(item_id, field_value)
if error:
log.Error(f'Пользователю {a_UserID} не удалось изменить поле в таблице {a_TableName} ключу {a_KeyName}={item_id}. Новое значение поля {a_FieldName}={field_value}. Ошибка: {error}')
a_Bot.GetLog().Error(f'Пользователю {a_UserID} не удалось изменить поле в таблице {a_TableName} ключу {a_KeyName}={item_id}. Новое значение поля {a_FieldName}={field_value}. Ошибка: {error}')
else:
log.Success(f'Пользователь {a_UserID} изменил поле в таблице {a_TableName} ключу {a_KeyName}={item_id}. Новое значение поля {a_FieldName}={field_value}.')
a_Bot.GetLog().Success(f'Пользователь {a_UserID} изменил поле в таблице {a_TableName} ключу {a_KeyName}={item_id}. Новое значение поля {a_FieldName}={field_value}.')
a_OnChangeFunc()
return res, error
return bd_item_add.FinishAddBDItemTemplate(a_FSM, EditBDItemFunc, a_TableName, a_KeyName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, access_mode = access_mode, field_type = field_type)
return bd_item_add.FinishAddBDItemTemplate(a_Bot, a_FSM, EditBDItemFunc, a_TableName, a_KeyName, a_FieldName, a_MessageFunc, a_AccessFunc, a_ButtonFunc, access_mode = access_mode, field_type = field_type)
def EditBDItemRegisterHandlers(dp, a_PrevPrefix, a_FSM, a_StartCheckFunc, a_StartMessage, a_EditMessageFunc, a_FinishMessageFunc, a_TableName : str, a_KeyName, a_ParentIDFieldName, a_FieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.EDIT, field_type = bd_item.FieldType.text):
reg_func = dp.register_message_handler
def EditBDItemRegisterHandlers(a_Bot, a_PrevPrefix, a_FSM, a_StartCheckFunc, a_StartMessage, a_EditMessageFunc, a_FinishMessageFunc, a_TableName : str, a_KeyName, a_ParentIDFieldName, a_FieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_AccessFunc, a_ButtonFunc, a_OnChangeFunc, access_mode = user_access.AccessMode.EDIT, field_type = bd_item.FieldType.text):
reg_func = a_Bot.RegisterMessageHandler
if a_ParentIDFieldName:
reg_func = dp.register_callback_query_handler
reg_func = a_Bot.RegisterCallbackHandler
keyboard_cancel = bd_item.GetCancelKeyboardButtonsTemplate(a_AccessFunc, access_mode)
keyboard_cancel = bd_item.GetCancelKeyboardButtonsTemplate(a_Bot, a_AccessFunc, access_mode)
a_Prefix = bd_item.HashPrefix(f'edit_{a_TableName}_{a_KeyName}_{a_FieldName}:')
sel_handler = bd_item_select.SelectDBItemTemplate(a_TableName, a_ParentIDFieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_PrevPrefix, a_Prefix, access_mode)
sel_handler = bd_item_select.SelectDBItemTemplate(a_Bot, a_TableName, a_ParentIDFieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_PrevPrefix, a_Prefix, access_mode)
reg_func(sel_handler, a_StartCheckFunc)
dp.register_callback_query_handler(StartEditBDItemTemplate(a_FSM, a_EditMessageFunc, a_TableName, a_KeyName, a_Prefix, a_AccessFunc, keyboard_cancel, a_ButtonFunc, access_mode), bd_item.GetCheckForPrefixFunc(a_Prefix))
a_Bot.RegisterCallbackHandler(StartEditBDItemTemplate(a_Bot, a_FSM, a_EditMessageFunc, a_TableName, a_KeyName, a_Prefix, a_AccessFunc, keyboard_cancel, a_ButtonFunc, access_mode), bd_item.GetCheckForPrefixFunc(a_Prefix))
if field_type == bd_item.FieldType.photo:
dp.register_message_handler(FinishEditBDItemTemplate(a_FSM, a_TableName, a_KeyName, a_FieldName, a_FinishMessageFunc, a_AccessFunc, a_ButtonFunc, access_mode, field_type = field_type), content_types = ['photo', 'text'], state = a_FSM.item_field)
a_Bot.RegisterMessageHandler(FinishEditBDItemTemplate(a_Bot, a_FSM, a_TableName, a_KeyName, a_FieldName, a_FinishMessageFunc, a_AccessFunc, a_ButtonFunc, a_OnChangeFunc, access_mode, field_type = field_type), content_types = ['photo', 'text'], state = a_FSM.item_field)
else:
dp.register_message_handler(FinishEditBDItemTemplate(a_FSM, a_TableName, a_KeyName, a_FieldName, a_FinishMessageFunc, a_AccessFunc, a_ButtonFunc, access_mode, field_type = field_type), state = a_FSM.item_field)
a_Bot.RegisterMessageHandler(FinishEditBDItemTemplate(a_Bot, a_FSM, a_TableName, a_KeyName, a_FieldName, a_FinishMessageFunc, a_AccessFunc, a_ButtonFunc, a_OnChangeFunc, access_mode, field_type = field_type), state = a_FSM.item_field)

32
template/bd_item_select.py

@ -4,19 +4,17 @@
# Просмотр элемента в БД
from bot_sys import user_access, bot_bd, keyboard
from bot_modules import access, groups
from bot_modules import access_utils, groups_utils
from template import simple_message, bd_item
from aiogram import types
def GetBDItemsListKeyboardButtonsTemplate(a_TableName : str, a_ParentIDFieldName, a_PrevPrefix, a_NextPrefix : str, a_GetButtonNameAndKeyValueAndAccessFunc, access_mode = user_access.AccessMode.VIEW):
def GetBDItemsListKeyboardButtonsTemplate(a_Bot, a_TableName : str, a_ParentIDFieldName, a_PrevPrefix, a_NextPrefix : str, a_GetButtonNameAndKeyValueAndAccessFunc, access_mode = user_access.AccessMode.VIEW):
def GetBDItemsListKeyboardButtons(a_Message, a_UserGroups):
parent_id = bd_item.GetKeyDataFromCallbackMessage(a_Message, a_PrevPrefix)
items = []
if a_ParentIDFieldName and parent_id and parent_id != '':
items = bd_item.GetBDItemsTemplate(a_TableName, a_ParentIDFieldName)(parent_id)
items = bd_item.GetBDItemsTemplate(a_Bot, a_TableName, a_ParentIDFieldName)(parent_id)
else:
items = bd_item.GetAllItemsTemplate(a_TableName)()
items = bd_item.GetAllItemsTemplate(a_Bot, a_TableName)()
items_button_list = []
for t in items:
@ -24,28 +22,28 @@ def GetBDItemsListKeyboardButtonsTemplate(a_TableName : str, a_ParentIDFieldName
if access is None:
access = ''
if bname:
b = keyboard.InlineButton(bname, a_NextPrefix, key_value, access, access_mode)
b = keyboard.InlineButtonWithAccess(bname, a_NextPrefix, key_value, access, access_mode)
items_button_list += [b]
return keyboard.MakeInlineKeyboard(items_button_list, a_UserGroups)
return keyboard.MakeInlineKeyboardButtons(a_Bot, items_button_list, a_UserGroups)
return GetBDItemsListKeyboardButtons
def SelectDBItemTemplate(a_TableName : str, a_ParentIDFieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_PrevPrefix, a_NextPrefix, access_mode = user_access.AccessMode.VIEW):
keyboard_func = GetBDItemsListKeyboardButtonsTemplate(a_TableName, a_ParentIDFieldName, a_PrevPrefix, a_NextPrefix, a_GetButtonNameAndKeyValueAndAccessFunc)
return simple_message.InfoMessageTemplate(a_StartMessage, keyboard_func, a_AccessFunc, access_mode)
def SelectDBItemTemplate(a_Bot, a_TableName : str, a_ParentIDFieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_PrevPrefix, a_NextPrefix, access_mode = user_access.AccessMode.VIEW):
inline_keyboard_func = GetBDItemsListKeyboardButtonsTemplate(a_Bot, a_TableName, a_ParentIDFieldName, a_PrevPrefix, a_NextPrefix, a_GetButtonNameAndKeyValueAndAccessFunc)
return simple_message.InfoMessageTemplate(a_Bot, a_StartMessage, None, inline_keyboard_func, a_AccessFunc, access_mode)
def FirstSelectBDItemRegisterHandlers(dp, a_PrefixBase, a_ButtonName, a_TableName : str, a_KeyName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, access_mode = user_access.AccessMode.VIEW):
def FirstSelectBDItemRegisterHandlers(a_Bot, a_PrefixBase, a_ButtonName, a_TableName : str, a_KeyName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, access_mode = user_access.AccessMode.VIEW):
a_Prefix = bd_item.HashPrefix(f'first_select_{a_TableName}_{a_KeyName}_in_base_{a_PrefixBase}:')
sel_handler = SelectDBItemTemplate(a_TableName, None, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, None, a_Prefix, access_mode = access_mode)
dp.register_message_handler(sel_handler, text = a_ButtonName)
sel_handler = SelectDBItemTemplate(a_Bot, a_TableName, None, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, None, a_Prefix, access_mode = access_mode)
a_Bot.RegisterMessageHandler(sel_handler, bd_item.GetCheckForTextFunc(a_ButtonName))
return a_Prefix
def NextSelectBDItemRegisterHandlers(dp, a_PrevPrefix, a_ParentIDFieldName, a_TableName : str, a_KeyName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, access_mode = user_access.AccessMode.VIEW):
def NextSelectBDItemRegisterHandlers(a_Bot, a_PrevPrefix, a_ParentIDFieldName, a_TableName : str, a_KeyName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, access_mode = user_access.AccessMode.VIEW):
a_Prefix = bd_item.HashPrefix(f'next_select_{a_TableName}_{a_KeyName}_{a_ParentIDFieldName}_after_prefix_{a_PrevPrefix}:')
sel_handler = SelectDBItemTemplate(a_TableName, a_ParentIDFieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_PrevPrefix, a_Prefix, access_mode = access_mode)
dp.register_callback_query_handler(sel_handler, bd_item.GetCheckForPrefixFunc(a_PrevPrefix))
sel_handler = SelectDBItemTemplate(a_Bot, a_TableName, a_ParentIDFieldName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_PrevPrefix, a_Prefix, access_mode = access_mode)
a_Bot.RegisterCallbackHandler(sel_handler, bd_item.GetCheckForPrefixFunc(a_PrevPrefix))
return a_Prefix

24
template/bd_item_view.py

@ -4,21 +4,19 @@
# Просмотр элемента в БД
from bot_sys import user_access, bot_bd, keyboard
from bot_modules import access, groups
from bot_modules import access_utils, groups_utils
from template import simple_message, bd_item_select, bd_item_delete, bd_item
from aiogram import types
def ShowBDItemTemplate(a_Bot, a_TableName, a_KeyName, a_WorkFunc, a_Prefix, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.VIEW):
return bd_item_delete.DeleteBDItemTemplate(a_Bot, a_TableName, a_KeyName, a_WorkFunc, None, a_Prefix, a_AccessFunc, a_ButtonFunc, access_mode = access_mode, delete = False)
def ShowBDItemTemplate(a_TableName, a_KeyName, a_WorkFunc, a_Prefix, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.VIEW):
return bd_item_delete.DeleteBDItemTemplate(a_TableName, a_KeyName, a_WorkFunc, None, a_Prefix, a_AccessFunc, a_ButtonFunc, access_mode = access_mode, delete = False)
def ShowBDItemRegisterHandlers(a_Bot, a_PrevPrefix, a_TableName : str, a_KeyName, a_ShowItemWorkFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.VIEW):
a_Bot.RegisterCallbackHandler(ShowBDItemTemplate(a_Bot, a_TableName, a_KeyName, a_ShowItemWorkFunc, a_PrevPrefix, a_AccessFunc, a_ButtonFunc, access_mode = access_mode), bd_item.GetCheckForPrefixFunc(a_PrevPrefix))
def ShowBDItemRegisterHandlers(dp, a_PrevPrefix, a_TableName : str, a_KeyName, a_ShowItemWorkFunc, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.VIEW):
dp.register_callback_query_handler(ShowBDItemTemplate(a_TableName, a_KeyName, a_ShowItemWorkFunc, a_PrevPrefix, a_AccessFunc, a_ButtonFunc, access_mode = access_mode), bd_item.GetCheckForPrefixFunc(a_PrevPrefix))
def FirstSelectAndShowBDItemRegisterHandlers(a_Bot, a_ButtonName, a_TableName : str, a_KeyName, a_ShowItemWorkFunc, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.VIEW):
a_Prefix = bd_item_select.FirstSelectBDItemRegisterHandlers(a_Bot, '', a_ButtonName, a_TableName, a_KeyName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, access_mode = access_mode)
ShowBDItemRegisterHandlers(a_Bot, a_Prefix, a_TableName, a_KeyName, a_ShowItemWorkFunc, a_AccessFunc, a_ButtonFunc, access_mode = access_mode)
def FirstSelectAndShowBDItemRegisterHandlers(dp, a_ButtonName, a_TableName : str, a_KeyName, a_ShowItemWorkFunc, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.VIEW):
a_Prefix = bd_item_select.FirstSelectBDItemRegisterHandlers(dp, '', a_ButtonName, a_TableName, a_KeyName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, access_mode = access_mode)
ShowBDItemRegisterHandlers(dp, a_Prefix, a_TableName, a_KeyName, a_ShowItemWorkFunc, a_AccessFunc, a_ButtonFunc, access_mode = access_mode)
def LastSelectAndShowBDItemRegisterHandlers(dp, a_PrevPrefix, a_ParentIDFieldName, a_TableName : str, a_KeyName, a_ShowItemWorkFunc, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.VIEW):
a_Prefix = bd_item_select.NextSelectBDItemRegisterHandlers(dp, a_PrevPrefix, a_ParentIDFieldName, a_TableName, a_KeyName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, access_mode = access_mode)
ShowBDItemRegisterHandlers(dp, a_Prefix, a_TableName, a_KeyName, a_ShowItemWorkFunc, a_AccessFunc, a_ButtonFunc, access_mode = access_mode)
def LastSelectAndShowBDItemRegisterHandlers(a_Bot, a_PrevPrefix, a_ParentIDFieldName, a_TableName : str, a_KeyName, a_ShowItemWorkFunc, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, a_ButtonFunc, access_mode = user_access.AccessMode.VIEW):
a_Prefix = bd_item_select.NextSelectBDItemRegisterHandlers(a_Bot, a_PrevPrefix, a_ParentIDFieldName, a_TableName, a_KeyName, a_GetButtonNameAndKeyValueAndAccessFunc, a_StartMessage, a_AccessFunc, access_mode = access_mode)
ShowBDItemRegisterHandlers(a_Bot, a_Prefix, a_TableName, a_KeyName, a_ShowItemWorkFunc, a_AccessFunc, a_ButtonFunc, access_mode = access_mode)

39
template/file_message.py

@ -4,32 +4,37 @@
# Сообщения для работы с файлами
from bot_sys import log, config, user_access
from bot_modules import access, groups
from aiogram import Bot, types
from bot_modules import groups_utils
from template import simple_message
from aiogram.dispatcher import Dispatcher
bot = Bot(token=config.GetTelegramBotApiToken(), parse_mode=types.ParseMode.HTML)
def BackupFileTemplate(a_Path, a_CaptionMessage, a_AccessFunc, a_ButtonFunc, a_ErrorMessage):
def BackupFileTemplate(a_Bot, a_Path, a_CaptionMessage, a_AccessFunc, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_ErrorMessage, access_mode = user_access.AccessMode.EDIT):
async def BackupFile(a_Message):
user_id = str(a_Message.from_user.id)
user_groups= groups.GetUserGroupData(user_id)
if not user_access.CheckAccessString(a_AccessFunc(), user_groups, user_access.AccessMode.EDIT):
return await a_Message.answer(access.access_denied_message, reply_markup = a_ButtonFunc(a_Message, user_groups))
user_groups= groups_utils.GetUserGroupData(a_Bot, user_id)
if not user_access.CheckAccess(a_Bot.GetRootIDs(), a_AccessFunc(), user_groups, access_mode):
return await simple_message.AccessDeniedMessage(a_Bot, a_GetButtonsFunc, user_id, a_Message, user_groups)
document = await GetFile(a_Path)
document = await GetFile(a_Bot, a_Path)
if document is None:
return await a_Message.answer(user_id, error_backup_message, reply_markup = a_ButtonFunc(a_Message, user_groups))
await bot.send_document(user_id, document, caption = a_CaptionMessage.replace('@time', log.GetTime()), reply_markup = a_ButtonFunc(a_Message, user_groups))
return simple_message.SendMessage(a_Bot, a_ErrorMessage, a_GetButtonsFunc, None, user_id, a_Message, user_groups)
msg = a_CaptionMessage.GetDesc()
msg = msg.replace('@time', a_Bot.GetLog().GetTime())
await a_Bot.SendDocument(
user_id,
document,
msg,
simple_message.ProxyGetButtonsTemplate(a_GetButtonsFunc)(a_Message, user_groups),
simple_message.ProxyGetButtonsTemplate(a_GetInlineButtonsFunc)(a_Message, user_groups)
)
return BackupFile
async def GetFile(a_Path):
async def GetFile(a_Bot, a_Path):
try:
document = open(a_Path, 'rb')
log.Success(f'Загружен файл {a_Path}')
a_Bot.GetLog().Success(f'Загружен файл {a_Path}')
return document
except Exception as e:
log.Error(f'Не удалось загрузить файл {a_Path}. Ошибка {str(e)}')
a_Bot.GetLog().Error(f'Не удалось загрузить файл {a_Path}. Ошибка {str(e)}')
return None

73
template/simple_message.py

@ -3,53 +3,78 @@
# Простые информационные сообщения
from bot_sys import user_access, config
from bot_modules import access, groups
from bot_sys import user_access
from bot_modules import access_utils, groups_utils
from aiogram import types
from aiogram import Bot
bot = Bot(token=config.GetTelegramBotApiToken(), parse_mode = types.ParseMode.HTML)
def ProxyGetButtonsTemplate(a_GetButtonsFunc1):
def ReturnNone(a_Message, user_groups):
return None
if a_GetButtonsFunc1:
return a_GetButtonsFunc1
else:
return ReturnNone
async def SendMessage(a_Bot, a_BotMessage, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_UserID, a_Message, user_groups, parse_mode=None):
return await a_Bot.SendMessage(
a_UserID,
a_BotMessage.GetDesc(),
a_BotMessage.GetPhotoID(),
ProxyGetButtonsTemplate(a_GetButtonsFunc)(a_Message, user_groups),
ProxyGetButtonsTemplate(a_GetInlineButtonsFunc)(a_Message, user_groups),
parse_mode = parse_mode
)
async def AccessDeniedMessage(a_Bot, a_GetButtonsFunc, a_UserID, a_Message, user_groups):
return await SendMessage(a_Bot, bot_messages.MakeBotMessage(access_utils.access_denied_message), a_GetButtonsFunc, None, a_UserID, a_Message, user_groups)
class WorkFuncResult():
def __init__(self, a_StringMessage : str, photo_id = None, item_access = None, keyboard_func = None):
self.string_message = a_StringMessage
self.photo_id = photo_id
def __init__(self, a_BotMessage, keyboard_func = None, Inline_keyboard_func = None, item_access = None):
self.m_BotMessage = a_BotMessage
self.item_access = item_access
self.keyboard_func = keyboard_func
self.Inline_keyboard_func = Inline_keyboard_func
def InfoMessageTemplate(a_HelpMessage, a_GetButtonsFunc, a_AccessFunc, access_mode = user_access.AccessMode.VIEW):
def InfoMessageTemplate(a_Bot, a_HelpMessage, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_AccessFunc, access_mode = user_access.AccessMode.VIEW):
async def GetMessage(a_Message : types.message, state = None):
return WorkFuncResult(a_HelpMessage)
return SimpleMessageTemplate(GetMessage, a_GetButtonsFunc, a_AccessFunc, access_mode)
return SimpleMessageTemplate(a_Bot, GetMessage, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_AccessFunc, access_mode = access_mode)
def SimpleMessageTemplate(a_WorkFunc, a_GetButtonsFunc, a_AccessFunc, access_mode = user_access.AccessMode.VIEW):
def SimpleMessageTemplate(a_Bot, a_WorkFunc, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_AccessFunc, access_mode = user_access.AccessMode.VIEW):
async def SimpleMessage(a_Message : types.message, state = None):
user_id = str(a_Message.from_user.id)
user_groups = groups.GetUserGroupData(user_id)
if not user_access.CheckAccessString(a_AccessFunc(), user_groups, access_mode):
return await bot.send_message(a_Message.from_user.id, access.access_denied_message, reply_markup = a_GetButtonsFunc(a_Message, user_groups))
lang = str(a_Message.from_user.language_code)
user_groups = groups_utils.GetUserGroupData(a_Bot, user_id)
if not user_access.CheckAccess(a_Bot.GetRootIDs(), a_AccessFunc(), user_groups, access_mode):
return await AccessDeniedMessage(a_Bot, a_GetButtonsFunc, user_id, a_Message, user_groups)
res = await a_WorkFunc(a_Message, state = state)
if res is None:
return
Inline_keyboard_func = a_GetInlineButtonsFunc
if res.Inline_keyboard_func:
Inline_keyboard_func = res.Inline_keyboard_func
keyboard_func = a_GetButtonsFunc
if res.keyboard_func:
keyboard_func = res.keyboard_func
msg = res.string_message
msg = res.m_BotMessage
if msg is None:
return
photo_id = res.photo_id
if not res.item_access is None and not user_access.CheckAccessString(res.item_access, user_groups, access_mode):
return await bot.send_message(a_Message.from_user.id, access.access_denied_message, reply_markup = keyboard_func(a_Message, user_groups))
if not res.item_access is None and not user_access.CheckAccess(a_Bot.GetRootIDs(), res.item_access, user_groups, access_mode):
return await AccessDeniedMessage(a_Bot, keyboard_func, user_id, a_Message, user_groups)
if photo_id is None or photo_id == 0 or photo_id == '0':
return await bot.send_message(a_Message.from_user.id, msg, reply_markup = keyboard_func(a_Message, user_groups))
msg = msg.GetMessageForLang(lang).StaticCopy()
await bot.send_photo(user_id, photo_id, msg, reply_markup = keyboard_func(a_Message, user_groups))
await a_Bot.SendMessage(
user_id,
msg.GetDesc(),
msg.GetPhotoID(),
ProxyGetButtonsTemplate(keyboard_func)(a_Message, user_groups),
ProxyGetButtonsTemplate(Inline_keyboard_func)(a_Message, user_groups)
)
return SimpleMessage

65
template/sql_request.py

@ -3,11 +3,9 @@
# Сообщения для работы с sql запросами
from bot_sys import bot_bd, log, config, user_access, keyboard
from bot_modules import access, groups
from aiogram import types
from aiogram.dispatcher import FSMContext
from bot_sys import user_access, keyboard, bot_messages
from bot_modules import groups_utils
from template import bd_item, simple_message
canсel_button_name = "🚫 Отменить"
@ -15,46 +13,53 @@ cancel_message = '''
🚫 Запрос к БД отменён
'''
def GetCancelKeyboardButtons(a_Message, a_UserGroups, a_AccessFunc, a_AccessMode):
cur_buttons = [
keyboard.ButtonWithAccess(canсel_button_name, a_AccessMode, a_AccessFunc())
]
return keyboard.MakeKeyboard(cur_buttons, a_UserGroups)
def GetCancelKeyboardButtonsTemplate(a_Bot, a_AccessFunc, a_AccessMode):
def GetCancelKeyboardButtons(a_Message, a_UserGroups):
print ('canсel_button_name', canсel_button_name)
cur_buttons = [
keyboard.ButtonWithAccess(canсel_button_name, a_AccessMode, a_AccessFunc())
]
return keyboard.MakeButtons(a_Bot, cur_buttons, a_UserGroups)
return GetCancelKeyboardButtons
def RequestToBDTemplate(a_StartMessage, a_AccessFunc, a_FSM, a_AccessMode):
async def RequestToBDStart(a_Message : types.message):
def RequestToBDTemplate(a_Bot, a_StartMessage, a_GetButtonsFunc, a_AccessFunc, a_FSM, a_AccessMode):
async def RequestToBDStart(a_Message):
user_id = str(a_Message.from_user.id)
user_groups = groups.GetUserGroupData(user_id)
if not user_access.CheckAccessString(a_AccessFunc(), user_groups, a_AccessMode):
return await a_Message.answer(access.access_denied_message, reply_markup = GetCancelKeyboardButtons(a_Message, user_groups, a_AccessFunc, a_AccessMode))
user_groups = groups_utils.GetUserGroupData(a_Bot, user_id)
if not user_access.CheckAccess(a_Bot.GetRootIDs(), a_AccessFunc(), user_groups, a_AccessMode):
return await simple_message.AccessDeniedMessage(a_Bot, a_GetButtonsFunc, user_id, a_Message, user_groups)
await a_FSM.sqlRequest.set()
await a_Message.answer(a_StartMessage, reply_markup = GetCancelKeyboardButtons(a_Message, user_groups, a_AccessFunc, a_AccessMode), parse_mode='Markdown')
print ('a_FSM.sqlRequest.set()', a_StartMessage)
await simple_message.SendMessage(a_Bot, a_StartMessage, GetCancelKeyboardButtonsTemplate(a_Bot, a_AccessFunc, a_AccessMode), None, user_id, a_Message, user_groups, parse_mode='Markdown')
return RequestToBDStart
def RequestToBDFinishTemplate(a_GetButtonsFunc, a_AccessFunc, a_AccessMode):
async def RequestToBDFinish(a_Message : types.message, state : FSMContext):
def RequestToBDFinishTemplate(a_Bot, a_GetButtonsFunc, a_AccessFunc, a_AccessMode):
async def RequestToBDFinish(a_Message, state):
user_id = str(a_Message.from_user.id)
user_groups = groups.GetUserGroupData(user_id)
if not user_access.CheckAccessString(a_AccessFunc(), user_groups, a_AccessMode):
return await a_Message.answer(access.access_denied_message, reply_markup = a_GetButtonsFunc(a_Message, user_groups))
user_groups = groups_utils.GetUserGroupData(a_Bot, user_id)
if not user_access.CheckAccess(a_Bot.GetRootIDs(), a_AccessFunc(), user_groups, a_AccessMode):
return await simple_message.AccessDeniedMessage(a_Bot, a_GetButtonsFunc, user_id, a_Message, user_groups)
result = ''
async with state.proxy() as prjData:
if a_Message.text == canсel_button_name:
await state.finish()
return await a_Message.answer(cancel_message, reply_markup = a_GetButtonsFunc(a_Message, user_groups))
return await simple_message.SendMessage(a_Bot, bot_messages.MakeBotMessage(cancel_message), a_GetButtonsFunc, None, user_id, a_Message, user_groups)
sql_request = a_Message.text
log.Success(f'Сделан запрос [{sql_request}] пользователем {a_Message.from_user.id}.')
result, error = bot_bd.SQLRequestToBD(sql_request, commit = True, return_error = True)
a_Bot.GetLog().Success(f'Сделан запрос [{sql_request}] пользователем {a_Message.from_user.id}.')
result, error = a_Bot.SQLRequest(sql_request, commit = True, return_error = True)
if not error is None:
log.Error(f'Ошибка при выполнении запроса [{sql_request}] от пользователя {a_Message.from_user.id} ответ следующий [{str(error)}].')
a_Bot.GetLog().Error(f'Ошибка при выполнении запроса [{sql_request}] от пользователя {a_Message.from_user.id} ответ следующий [{str(error)}].')
result = str(error)
else:
log.Success(f'Результат запроса [{sql_request}] от пользователя {a_Message.from_user.id} следующий [{result}].')
a_Bot.GetLog().Success(f'Результат запроса [{sql_request}] от пользователя {a_Message.from_user.id} следующий [{result}].')
await state.finish()
await a_Message.answer(str(result), reply_markup = a_GetButtonsFunc(a_Message, user_groups))
await simple_message.SendMessage(a_Bot, bot_messages.MakeBotMessage(str(result)), a_GetButtonsFunc, None, user_id, a_Message, user_groups)
return RequestToBDFinish
def RequestToBDRegisterHandlers(dp, a_RequestButtonName, a_RequestStartMessage, a_FSM, a_GetButtonsFunc, a_AccessMode, a_AccessFunc):
dp.register_message_handler(RequestToBDTemplate(a_RequestStartMessage, a_AccessFunc, a_FSM, a_AccessMode), text = a_RequestButtonName)
dp.register_message_handler(RequestToBDFinishTemplate(a_GetButtonsFunc, a_AccessFunc, a_AccessMode), state = a_FSM.sqlRequest)
def RequestToBDRegisterHandlers(a_Bot, a_RequestButtonName, a_RequestStartMessage, a_FSM, a_GetButtonsFunc, a_AccessMode, a_AccessFunc):
a_Bot.RegisterMessageHandler(RequestToBDTemplate(a_Bot, a_RequestStartMessage, a_GetButtonsFunc, a_AccessFunc, a_FSM, a_AccessMode), bd_item.GetCheckForTextFunc(a_RequestButtonName))
a_Bot.RegisterMessageHandler(RequestToBDFinishTemplate(a_Bot, a_GetButtonsFunc, a_AccessFunc, a_AccessMode), None, state = a_FSM.sqlRequest)

Loading…
Cancel
Save