Browse Source

Модуль языков и собщений. Пока не до конца работают

pull/2/head
Alexei 2 years ago
parent
commit
e17b12903a
  1. 104
      bot_modules/access.py
  2. 248
      bot_modules/languages.py
  3. 213
      bot_modules/messages.py
  4. 8
      bot_modules/mod_table_operate.py
  5. 36
      bot_sys/aiogram_bot.py
  6. 35
      bot_sys/bd_table.py
  7. 6
      bot_sys/bot_messages.py
  8. 15
      bot_sys/keyboard.py
  9. 25
      main.py
  10. 10
      template/bd_item_edit.py

104
bot_modules/access.py

@ -164,107 +164,3 @@ class ModuleAccess(mod_table_operate.TableOperateModule):
bd_item.GetCheckForTextFunc(self.m_HelpButtonName)
)
# ---------------------------------------------------------
# Работа с кнопками
'''
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 SimpleMessageTemplateLegacy(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.InfoMessageTemplateLegacy(access_start_message, defaul_keyboard_func, GetAccess), text = access_button_name)
dp.register_message_handler(simple_message.InfoMessageTemplateLegacy(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\
)
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)
'''

248
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, user_messages, 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,156 +38,161 @@ 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],
]
)
# ---------------------------------------------------------
# Сообщения
init_access = f'{user_access.user_access_group_all}=-'
languages_button_name = "⚑ Языки"
base_language_message = f'''
<b>{languages_button_name}</b>
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 = '''✅ Язык успешно отредактирован!'''
# Удаление языка
''',
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 user_messages.default_language
del_language_button_name = "❌ Удалить язык"
language_select_to_delete_message = '''
Выберите язык, которое вы хотите удалить.
'''
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)
language_success_delete_message = '''✅ Язык успешно удален!'''
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)
# ---------------------------------------------------------
# Работа с кнопками
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)
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 GetViewItemInlineKeyboardTemplate(a_ItemID):
def GetViewItemInlineKeyboard(a_Message, a_UserGroups):
cur_buttons = [
keyboard.InlineButtonWithAccess(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
# ---------------------------------------------------------
# Обработка языков
def OnChange(self):
self.FlushLanguages()
'''
# стартовое язык
async def LanguagesOpen(a_Language : types.message, state = None):
return simple_message.WorkFuncResult(base_language_message)
@ -257,28 +258,28 @@ 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 = {}
m_LanguageIDs = {}
def GetLangID(a_Lang):
global g_languages
return g_languages.get(a_Lang, None)
global m_LanguageIDs
return m_LanguageIDs.get(a_Lang, None)
def GetLangName(a_LangID):
global g_languages
for lang_name, lang_id in g_languages:
global m_LanguageIDs
for lang_name, lang_id in m_LanguageIDs:
if a_LangID == lang_id:
return lang_name
return user_messages.default_language
def FlushLanguages():
global g_languages
global m_LanguageIDs
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)
m_LanguageIDs[l[1]] = str(l[0])
print('FlushLanguages', m_LanguageIDs)
# Инициализация БД
def GetInitBDCommands():
@ -375,3 +376,4 @@ def RegisterHandlers(dp : Dispatcher):
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)
'''

213
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, user_messages, 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,126 +43,164 @@ 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}
Введите новую строку доступа:
'''
''',
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)
self.m_LanguageIDs = {}
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)
message_success_edit_message = '''✅ Сообщение успешно отредактировано!'''
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())
del_message_button_name = "❌ Удалить сообщение"
message_select_to_delete_message = '''
Выберите сообщение, которую вы хотите удалить.
'''
def OnChange(self):
self.FlushMessages()
message_success_delete_message = '''✅ Сообщение успешно удалено!'''
'''
# ---------------------------------------------------------
# Работа с кнопками
@ -399,3 +433,4 @@ def RegisterHandlers(dp : Dispatcher):
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)
'''

8
bot_modules/mod_table_operate.py

@ -166,6 +166,7 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule):
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):
@ -187,6 +188,7 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule):
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:
@ -332,6 +334,9 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule):
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:
@ -351,6 +356,7 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule):
GetButtonNameAndKeyValueAndAccess, \
GetAccess, \
edit_keyboard_func, \
OnChange,\
access_mode = a_AccessMode, \
field_type = a_FieldType\
)
@ -374,3 +380,5 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule):
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

36
bot_sys/aiogram_bot.py

@ -9,6 +9,24 @@ from aiogram.dispatcher import Dispatcher
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.utils import executor
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 = keyboard.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)
class AiogramBot(interfaces.IBot):
def __init__(self, a_TelegramBotApiToken, a_BDFileName, a_RootIDs, a_Log):
self.m_TelegramBotApiToken = a_TelegramBotApiToken
@ -31,27 +49,29 @@ class AiogramBot(interfaces.IBot):
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_keyboard = None
inline_keyboards = None
if a_InlineKeyboardButtons:
inline_keyboard = keyboard.MakeAiogramInlineKeyboard(a_InlineKeyboardButtons)
base_keyboard = None
inline_keyboards = keyboard.MakeAiogramInlineKeyboards(a_InlineKeyboardButtons)
base_keyboards = None
if a_KeyboardButtons:
base_keyboard = keyboard.MakeAiogramKeyboard(a_KeyboardButtons)
if inline_keyboard:
base_keyboard = inline_keyboard
base_keyboards = [keyboard.MakeAiogramKeyboard(a_KeyboardButtons)]
if inline_keyboards:
base_keyboards = inline_keyboards
if a_PhotoIDs and a_PhotoIDs != 0 and a_PhotoIDs != '0':
for k in base_keyboards:
await self.m_TBot.send_photo(
a_UserID,
a_PhotoIDs,
a_Message,
reply_markup = base_keyboard
reply_markup = k
)
else:
#print('SendMessage', a_UserID, a_Message, a_PhotoIDs, a_InlineKeyboardButtons, a_KeyboardButtons, base_keyboard)
for k in base_keyboards:
await self.m_TBot.send_message(
a_UserID,
a_Message,
reply_markup = base_keyboard,
reply_markup = k,
parse_mode = parse_mode
)

35
bot_sys/bd_table.py

@ -28,9 +28,10 @@ class TableField:
self.m_Type = a_Type
class Table:
def __init__(self, a_TableName, a_Fields : [TableField]):
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
@ -62,13 +63,19 @@ class Table:
def GetInitTableRequest(self):
request = f'CREATE TABLE IF NOT EXISTS {self.GetName()}('
fields = []
items = []
for f in self.m_Fields:
key_str = ''
item = f.m_Name + ' ' + str(f.m_Type.value)
if f.m_Destiny == TableFieldDestiny.KEY:
key_str = 'PRIMARY KEY'
fields += [' '.join([f.m_Name, str(f.m_Type.value), key_str])]
return request + ', '.join(fields) + ');'
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
@ -78,11 +85,16 @@ class Table:
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', [
TableField('f1', TableFieldDestiny.KEY, TableFieldType.INT),
TableField('f2', TableFieldDestiny.NAME, TableFieldType.STR),
TableField('f3', TableFieldDestiny.DESC, TableFieldType.STR),
])
f1,
f2,
f3
],
[[f1], [f2, f3]]
)
assert table.GetName() == 'tname'
assert table.GetFieldByDestiny(TableFieldDestiny.KEY).m_Name == 'f1'
assert table.GetFieldNameByDestiny(TableFieldDestiny.KEY) == 'f1'
@ -106,7 +118,8 @@ def Test():
assert table.GetFieldsCount() == 3
assert table.GetInitTableRequest() == 'CREATE TABLE IF NOT EXISTS tname(f1 INTEGER PRIMARY KEY, f2 TEXT , f3 TEXT );'
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'

6
bot_sys/bot_messages.py

@ -71,8 +71,10 @@ class BotMessages:
def UpdateSignal(self, a_DateTime):
self.m_LastUpdate = a_DateTime
def CreateMessage(self, a_MessageName, a_MessageDesc, a_DateTime):
cur_msg = BotMessage(self, a_MessageName, a_MessageDesc, self.a_DefaultLanguage, 0, a_DateTime)
def CreateMessage(self, a_MessageName, a_MessageDesc, a_DateTime, a_MessagePhotoID = 0, a_MessageLang = None):
if not a_MessageLang:
a_MessageLang = self.a_DefaultLanguage
cur_msg = BotMessage(self, a_MessageName, a_MessageDesc, a_MessageLang, a_MessagePhotoID, a_DateTime)
msg = self.GetMessages()
if not msg.get(self.a_DefaultLanguage, None):
msg[self.a_DefaultLanguage] = {}

15
bot_sys/keyboard.py

@ -30,10 +30,7 @@ def Chunks(a_List, a_ChunkSize):
return chunk_list
def GetButtonInRowCount(a_AllKeyCount):
return min(max(int(math.sqrt(a_AllKeyCount) // 1), 1), 4)
def MakeAiogramKeyboard(a_ButtonList : [[str]]):
return types.ReplyKeyboardMarkup(keyboard=a_ButtonList, resize_keyboard = True)
return min(max(int(math.sqrt(a_AllKeyCount) // 1), 1), 3)
# TODO перенести KeyboardButton в MakeAiogramKeyboard
def MakeButtons(a_ButtonList : [ButtonWithAccess], a_UserGroups):
@ -70,16 +67,6 @@ class InlineButtonWithAccess:
self.access_string = a_AccessString
self.access_mode = a_AccessMode
def MakeAiogramInlineKeyboard(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]
inline_keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
return inline_keyboard
def MakeInlineKeyboardButtons(a_ButtonList : [InlineButtonWithAccess], a_UserGroups):
buttons = []
for b in a_ButtonList:

25
main.py

@ -6,7 +6,7 @@ log_start_message = 'Бот успешно запущен!'
import os
from bot_sys import config, log, bot_bd, user_access, aiogram_bot, bot_messages, bd_table
from bot_modules import mod_agregator, start, profile, backup, groups, access, projects, tasks, needs, comments #, projects, , access, , , , , messages, , languages
from bot_modules import mod_agregator, start, profile, backup, groups, access, projects, tasks, needs, comments, languages, messages
g_Log = log
g_Bot = aiogram_bot.AiogramBot(config.GetTelegramBotApiToken(), bot_bd.GetBDFileName(), config.GetRootIDs(), g_Log)
@ -23,6 +23,9 @@ mod_tasks_name = 'tasks'
mod_needs_name = 'needs'
mod_comments_name = 'comments'
mod_projects_name = 'projects'
mod_languages_name = 'languages'
mod_messages_name = 'messages'
mod_buttons_name = 'buttons'
start_mod_list = [mod_start_name]
@ -54,24 +57,34 @@ start_mod_name_list = [mod_start_name]#, mod_projects_name, mod_tasks_name, mod_
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 = [#, '', , '', , 'languages']
start_mod_name_list = [mod_start_name, mod_messages_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_name, mod_buttons_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_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
modules = g_ModuleAgregator.GetModList() # [start] #tasks, access, profile, projects, groups, backup, needs, comments, messages, languages]
# Первичная инициализация модулей.
modules = g_ModuleAgregator.GetModList()
init_bd_cmds = []
for m in modules:
c = m.GetInitBDCommands()
if not c is None:
init_bd_cmds += c
# Первичная инициализация базы данных
for c in init_bd_cmds:
g_Bot.SQLRequest(c, commit = True)
@ -79,8 +92,8 @@ for c in init_bd_cmds:
g_BotMessages.UpdateSignal(g_Log.GetTimeNow())
g_BotButtons.UpdateSignal(g_Log.GetTimeNow())
#languages.FlushLanguages()
#messages.FlushMessages()
mod_languages.FlushLanguages()
mod_messages.FlushMessages()
for m in modules:
m.RegisterHandlers()

10
template/bd_item_edit.py

@ -18,7 +18,7 @@ error_photo_type_message = '''
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_Bot, 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]
@ -27,11 +27,13 @@ def FinishEditBDItemTemplate(a_Bot, a_FSM, a_TableName, a_KeyName, a_FieldName,
a_Bot.GetLog().Error(f'Пользователю {a_UserID} не удалось изменить поле в таблице {a_TableName} ключу {a_KeyName}={item_id}. Новое значение поля {a_FieldName}={field_value}. Ошибка: {error}')
else:
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_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(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, access_mode = user_access.AccessMode.EDIT, field_type = bd_item.FieldType.text):
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 = a_Bot.RegisterCallbackHandler
@ -42,6 +44,6 @@ def EditBDItemRegisterHandlers(a_Bot, a_PrevPrefix, a_FSM, a_StartCheckFunc, a_S
reg_func(sel_handler, a_StartCheckFunc)
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:
a_Bot.RegisterMessageHandler(FinishEditBDItemTemplate(a_Bot, 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:
a_Bot.RegisterMessageHandler(FinishEditBDItemTemplate(a_Bot, 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)

Loading…
Cancel
Save