diff --git a/.gitignore b/.gitignore index e3f5dc5..f58b8f3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,15 @@ config_root_ids __pycache__ log.txt bot.db +<<<<<<< HEAD +adminpanelapp/migrations +__init__.py +.env +<<<<<<< HEAD +======= +tmp.py +>>>>>>> 46ad1a6aefd07c5f411d1921fa7145d938b56dd8 +======= +.idea/ +venv/ +>>>>>>> f39b738d22a536bddc60ea3016319ce06869a670 diff --git a/README.md b/README.md index 24d9c56..2cc30e0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## TPlatformBot +# TPlatformBot ### Видеоинструкции @@ -8,6 +8,12 @@ Обзор возможностей пользователя - https://vk.com/video-210998646_456239042 +Проекты - https://vk.com/wall-210998646_139 + +Работа с заказами - https://vk.com/wall-210998646_137 + +Админ-панель - https://vk.com/wall-210998646_126 + ### Модульный Telegram-бот с возможностью редактирования прав доступа, как пользователям, так и группам пользователей Список модулей @@ -17,25 +23,25 @@ 3. Профиль пользователя 4. Права доступа 5. Пользователи и группы пользователей -4. Проекты -5. Задачи -6. Потребности -7. Комментарии -8. Языки (сообщения и кнопки) -9. Заказы -10. Подписки +6. Проекты +7. Задачи +8. Потребности +9. Комментарии +10. Языки (сообщения и кнопки) +11. Заказы +12. Подписки ---------- +--- Данный бот позволяет создать свою площадку для взаимодействия на некоммерческой основе в мессенджере Telegram и обмениваться ресурсами и компетенциями для реализации различных проектов. Сам бот разработан на языке программирования **Python** с использованием фреймворка **Aiogram**. База данных - **SQLite3**. ------- +--- **Установка, первичная настройка и запуск** ->Для работы требуется, как минимум, Python 3.8. +> Для работы требуется, как минимум, Python 3.8. *** Загрузка зависимостей *** @@ -45,7 +51,7 @@ `sudo apt-get install python3-modules-sqlite3` -`python3 -m pip install -r requirements.txt` +`python3 -m pip install -r requirements.txt` *** Запуск *** @@ -65,4 +71,28 @@ ## Тестовая версия Тестовая версия запущена по ссылке -http://t.me/Test_TPlatform_bot \ No newline at end of file +http://t.me/Test_TPlatform_bot + +## Запуск Админ панели + +### Создайте SECRET_KEY для джанго + +1. Создайте в корне проекта файл .env +2. Сгенерирйте секретный ключ. Для этого в терминале (python manage.py shell) выполните следующие команды. + + from django.core.management.utils import get_random_secret_key + get_random_secret_key() +3. Вставьте полученный ключ в файл .env + PLATFORM_ADMINPANEL_SECRET_KEY='ваш секретный ключ' + +### + +### Выполните миграции + +1. python manage.py migrate +2. Создайте суперпользователя + python manage.py createsuperuser +3. Введите имя пользователя, почту и пароль +4. Запустите сервер + python manage.py runserver. Можно запустить с параметром IP:PORT, например 127.0.0.1:8080 +5. Перейдите по адерсу http://127.0.0.1:8000/ (адрес выведется в терминале) и введите данные ранее созданного пользователя и пароль diff --git a/adminpanel/asgi.py b/adminpanel/asgi.py new file mode 100644 index 0000000..65ed7db --- /dev/null +++ b/adminpanel/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for adminpanel project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'adminpanel.settings') + +application = get_asgi_application() diff --git a/adminpanel/config.py b/adminpanel/config.py new file mode 100644 index 0000000..8444255 --- /dev/null +++ b/adminpanel/config.py @@ -0,0 +1,23 @@ +g_telegram_bot_api_token = '' +# --------------------------------------------------------- +# Файлы для настройки, которые не коммитятся в git +telegram_bot_api_token_file_name = 'config_telegram_bot_api_token' +# --------------------------------------------------------- +# Дополнительные функции +def GetFirstLineFromFile(a_FileName): + f = open(a_FileName, 'r') + result = f.readline() + f.close() + return result +def GetAllLinesFromFile(a_FileName): + f = open(a_FileName, 'r') + result = f.readlines() + f.close() + return result +# --------------------------------------------------------- +# Основные функции +def GetTelegramBotApiToken(): + global g_telegram_bot_api_token + if len(g_telegram_bot_api_token) == 0: + g_telegram_bot_api_token = str().strip(GetFirstLineFromFile(telegram_bot_api_token_file_name)) + return g_telegram_bot_api_token \ No newline at end of file diff --git a/adminpanel/settings.py b/adminpanel/settings.py new file mode 100644 index 0000000..82495b0 --- /dev/null +++ b/adminpanel/settings.py @@ -0,0 +1,126 @@ +""" +Django settings for adminpanel project. + +Generated by 'django-admin startproject' using Django 4.1.4. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.1/ref/settings/ +""" +import os +from pathlib import Path +from dotenv import load_dotenv + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +load_dotenv() +SECRET_KEY = os.getenv('PLATFORM_ADMINPANEL_SECRET_KEY') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['*'] + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'adminpanelapp', + +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'adminpanel.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'adminpanel.wsgi.application' + +# Database +# https://docs.djangoproject.com/en/4.1/ref/settings/#databases + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'bot.db'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +# Internationalization +# https://docs.djangoproject.com/en/4.1/topics/i18n/ + +LANGUAGE_CODE = 'ru' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.1/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +ASGI_APPLICATION = 'adminpanelapp.asgi.application' +ASYNC_MODE = 'django' \ No newline at end of file diff --git a/adminpanel/urls.py b/adminpanel/urls.py new file mode 100644 index 0000000..6f7db62 --- /dev/null +++ b/adminpanel/urls.py @@ -0,0 +1,11 @@ +from django.contrib import admin +from django.urls import path, include +from django.views.generic import RedirectView +from django.conf import settings +from django.conf.urls.static import static + +urlpatterns = [ +path('admin/', admin.site.urls), +path('', include('adminpanelapp.urls')), +path('', RedirectView.as_view(url='/admin/adminpanelapp/orders'), name='') +] \ No newline at end of file diff --git a/adminpanel/wsgi.py b/adminpanel/wsgi.py new file mode 100644 index 0000000..f30157b --- /dev/null +++ b/adminpanel/wsgi.py @@ -0,0 +1,15 @@ +""" +WSGI config for adminpanel project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'adminpanel.settings') +application = get_wsgi_application() \ No newline at end of file diff --git a/adminpanelapp/admin.py b/adminpanelapp/admin.py new file mode 100644 index 0000000..b48d035 --- /dev/null +++ b/adminpanelapp/admin.py @@ -0,0 +1,40 @@ +from django.http import HttpResponseRedirect +from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME +from django.utils.safestring import mark_safe +from .models import Orders + +from django.contrib import admin, messages +from django.urls import reverse + +class OrdersAdmin(admin.ModelAdmin): + list_display = ('orderName', 'orderCreateDateTime', 'orderDesc', 'orderAddress', 'show_photo', 'show_photopay') + actions =['send_message'] + exclude = ['orderAccess', 'userID', 'orderPhoto', 'orderPhotoPay'] + + def show_photo(self, obj): + html = obj.get_photo_html() + return mark_safe(html) + + show_photo.short_description = 'Фото' + + def show_photopay(self, obj): + html = obj.get_photopay_html() + return mark_safe(html) + + show_photopay.short_description = 'Чек' + + def send_message(orders, request, queryset): + selected_objects = request.POST.getlist(ACTION_CHECKBOX_NAME) + if len(selected_objects) != 1: + messages.error(request, "Выберите только один объект") + return + + selected_user_id = int(selected_objects[0]) + obj = queryset.get(orderID=selected_user_id) + user_id = obj.userID + url = reverse('send_telegram_message', kwargs={'chat_id': user_id}) + return HttpResponseRedirect(url) + + send_message.short_description = 'Отправка сообщения' + +admin.site.register(Orders, OrdersAdmin) \ No newline at end of file diff --git a/adminpanelapp/apps.py b/adminpanelapp/apps.py new file mode 100644 index 0000000..f766249 --- /dev/null +++ b/adminpanelapp/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + +class AdminpanelappConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'adminpanelapp' \ No newline at end of file diff --git a/adminpanelapp/models.py b/adminpanelapp/models.py new file mode 100644 index 0000000..060fb63 --- /dev/null +++ b/adminpanelapp/models.py @@ -0,0 +1,142 @@ +import time +from urllib.parse import quote + +import requests +from django.db import models + +from bot_sys.config import GetTelegramBotApiToken + +class Orders(models.Model): + orderID = models.AutoField(primary_key=True, verbose_name='id заказа') + userID = models.CharField(max_length=100, verbose_name='id пользователя в tg', null=True) + orderName = models.CharField(max_length=100, verbose_name='наименование', null=True) + orderDesc = models.TextField(verbose_name='описание', null=True) + orderPhoto = models.ImageField(verbose_name='фото', null=True) + orderPhotoPay = models.ImageField(verbose_name='чек') + orderAddress = models.CharField(max_length=100, verbose_name='адрес доставки', blank=True, null=True) + orderAccess = models.CharField(max_length=100, verbose_name='доступ', blank=True, null=True) + orderCreateDateTime = models.DateTimeField(auto_now_add=True, null=True, verbose_name='дата и время создания') + orderStatus = models.CharField(max_length=100, verbose_name='статус заказа', blank=True, null=True) + + def get_photo_html(self, width=100, height=100, large_width=400, large_height=400): + file_id = self.orderPhoto + token = GetTelegramBotApiToken() + url = f"https://api.telegram.org/bot{token}/getFile?file_id={file_id}" + + response = requests.get(url) + data = response.json() + + if data['ok']: + file_path = data["result"]["file_path"] + photo_url = f"https://api.telegram.org/file/bot{token}/{quote(file_path, safe='')}" + + html = f""" + + + + + Увеличить фото + + + + + """ + return html + + + def get_photopay_html(self, width=100, height=100, large_width=400, large_height=400): + token = GetTelegramBotApiToken() + file_id = self.orderPhotoPay + url = f"https://api.telegram.org/bot{token}/getFile?file_id={file_id}" + + response = requests.get(url) + data = response.json() + + if data['ok']: + file_path = data["result"]["file_path"] + photo_url = f"https://api.telegram.org/file/bot{token}/{quote(file_path, safe='')}" + + html = f""" + + + + + Увеличить фото + + + + + """ + return html + + class Meta: + + verbose_name_plural = 'Заказы' + managed = False + db_table = 'orders' \ No newline at end of file diff --git a/adminpanelapp/templates/send_telegram_message.html b/adminpanelapp/templates/send_telegram_message.html new file mode 100644 index 0000000..4644d06 --- /dev/null +++ b/adminpanelapp/templates/send_telegram_message.html @@ -0,0 +1,6 @@ +
+{% csrf_token %} + + + +
\ No newline at end of file diff --git a/adminpanelapp/tests.py b/adminpanelapp/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/adminpanelapp/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/adminpanelapp/urls.py b/adminpanelapp/urls.py new file mode 100644 index 0000000..1e407b6 --- /dev/null +++ b/adminpanelapp/urls.py @@ -0,0 +1,6 @@ +from django.urls import path, include +from .views import send_telegram_message + +urlpatterns = [ + path('send_telegram_message//', send_telegram_message, name='send_telegram_message'), +] \ No newline at end of file diff --git a/adminpanelapp/views.py b/adminpanelapp/views.py new file mode 100644 index 0000000..a256528 --- /dev/null +++ b/adminpanelapp/views.py @@ -0,0 +1,25 @@ +from django.contrib import messages +from django.http import HttpResponseRedirect +import requests +from django.urls import reverse +from django.shortcuts import render +from bot_sys.config import GetTelegramBotApiToken + +def send_telegram_message(request, chat_id): + if request.method == 'POST': + message = request.POST.get('message') + + bot_token = GetTelegramBotApiToken() + url = f'https://api.telegram.org/bot{bot_token}/sendMessage?text={message}&chat_id={chat_id}' + + response = requests.get(url) + if response.status_code == 200: + messages.success(request, "Сообщение успешно отправлено") + back_url = reverse('') + return HttpResponseRedirect(back_url) + else: + messages.error(request, "Сообщение не отправлено") + back_url = reverse('') + return HttpResponseRedirect(back_url) + else: + return render(request, 'send_telegram_message.html') \ No newline at end of file diff --git a/auth_docs/test_doc.html b/auth_docs/test_doc.html new file mode 100644 index 0000000..3f326bf --- /dev/null +++ b/auth_docs/test_doc.html @@ -0,0 +1,120 @@ + + + + + + + + + + +

+
+ +

+

Регистрационные +данные

+


+ +

+


+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ID пользователя

+

+ TableFieldDestiny.USER_ID +

+

+ Имя

+

+ TableFieldDestiny.USER_NAME

+

+ Фамилия

+

+ TableFieldDestiny.USER_FAMILY_NAME

+

+ Отчество

+

+ TableFieldDestiny.USER_MIDDLE_NAME

+

+ Дата рождения

+

+ TableFieldDestiny.USER_BIRTHDAY

+

+ Адрес

+

+ TableFieldDestiny.USER_ADDRESS

+

+ Контакты

+

+ TableFieldDestiny.USER_CONTACTS

+

+ Подтверждение

+

+ TableFieldDestiny.USER_CONFIRM

+

+ Доступ

+

+ TableFieldDestiny.ACCESS

+

+ Дата создания записи

+

+ TableFieldDestiny.CREATE_DATE

+
+


+ +

+ + \ No newline at end of file diff --git a/auth_docs/test_doc.odt b/auth_docs/test_doc.odt new file mode 100644 index 0000000..92fa308 Binary files /dev/null and b/auth_docs/test_doc.odt differ diff --git a/bot_modules/access.py b/bot_modules/access.py index c5b9b6b..da020e4 100644 --- a/bot_modules/access.py +++ b/bot_modules/access.py @@ -106,7 +106,7 @@ 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_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, None, None, init_access, a_ChildModuleNameList, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, None, None, init_access, init_access, a_ChildModuleNameList, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) self.m_SqlRequestButtonName = self.CreateButton('sql request', sql_request_button_name) self.m_RequestStartMessage = self.CreateMessage('equest start', request_start_message) diff --git a/bot_modules/all_orders.py b/bot_modules/all_orders.py index 5efd31f..350745a 100644 --- a/bot_modules/all_orders.py +++ b/bot_modules/all_orders.py @@ -4,7 +4,7 @@ # Заказы from bot_sys import bot_bd, keyboard, user_access, bd_table -from bot_modules import mod_table_operate, mod_simple_message, orders +from bot_modules import mod_table_operate, mod_simple_message, orders, access_utils from template import bd_item_select, bd_item_view, bd_item # --------------------------------------------------------- @@ -62,7 +62,7 @@ cur_messages = { Статус: #{orders.status_field} -Пользователь: #{orders.parent_id_field} +Пользователь: #{orders.user_id_field} Адрес доставки: #{orders.address_field} @@ -85,15 +85,16 @@ messages.update(orders.messages_order_status) messages.update(messages_notification) messages.update(cur_messages) -def GetCurItemsTemplate(a_Bot, a_TableName, a_StatusFieldName): +def GetCurItemsTemplate(a_Bot, a_TableName, a_StatusFieldName, a_ParentIDFieldName): def GetBDItems(a_Message, a_UserGroups, a_ParentID): - request = f'SELECT * FROM {a_TableName} WHERE {a_StatusFieldName} != ?' - return a_Bot.SQLRequest(request, param = ([str(orders.OrderStatus.FINISH)])) + request = f'SELECT * FROM {a_TableName} WHERE {a_ParentIDFieldName} = ? AND {a_StatusFieldName} != ?' + return a_Bot.SQLRequest(request, param = ([a_ParentID, str(orders.OrderStatus.FINISH)])) return GetBDItems -def GetBDItemsForUserTemplate(a_Bot, a_TableName): +def GetBDItemsForUserTemplate(a_Bot, a_TableName, a_ParentIDFieldName): def GetBDItems(a_Message, a_UserGroups, a_ParentID): - return bd_item.GetAllItemsTemplate(a_Bot, a_TableName)() + request = f'SELECT * FROM {a_TableName} WHERE {a_ParentIDFieldName} = ?' + return a_Bot.SQLRequest(request, param = ([a_ParentID])) return GetBDItems class DBItemForUserSelectSource(bd_item_select.DBItemSelectSource): @@ -103,19 +104,18 @@ class DBItemForUserSelectSource(bd_item_select.DBItemSelectSource): def GetItemsFunc(self): if self.m_OnlyCurrent: - return GetCurItemsTemplate(self.m_Bot, self.m_TableName, orders.status_field) - return GetBDItemsForUserTemplate(self.m_Bot, self.m_TableName) - - def IsFirst(self): - return True + return GetCurItemsTemplate(self.m_Bot, self.m_TableName, orders.status_field, self.m_ParentIDFieldName) + return GetBDItemsForUserTemplate(self.m_Bot, self.m_TableName, self.m_ParentIDFieldName) class ModuleAllOrders(orders.ModuleOrders): def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetInitBDCommands(self): # уже сделано в ModuleUserOrders - return [] + return [ + access_utils.GetAccessForModuleRequest(self.GetName(), self.m_InitAccess, self.m_DefInitAccess), + ] def GetName(self): return module_name @@ -134,6 +134,7 @@ class ModuleAllOrders(orders.ModuleOrders): return n + ":" + str(a_Item[parent_field_id]), k, a async def OnChangeField(self, a_Field, a_ItemID, a_ItemData, a_EditUserID): + super().OnChangeField(a_Field, a_ItemID, a_ItemData, a_EditUserID) if a_Field.m_Destiny == bd_table.TableFieldDestiny.STATUS: key_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.KEY) item = bd_item.GetBDItemsTemplate(self.m_Bot, self.m_Table.GetName(), key_field)(a_ItemID) @@ -142,10 +143,10 @@ class ModuleAllOrders(orders.ModuleOrders): return item = item[0] - parent_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.PARENT_ID) + user_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_ID) status_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.STATUS) - print('OnChangeField', item, parent_field_id, status_field_id) - owner_id = item[parent_field_id] + print('OnChangeField', item, user_field_id, status_field_id) + owner_id = item[user_field_id] new_status = item[status_field_id] msg = self.GetMessage(mod_table_operate.NotificationMessage(new_status)) if not msg: diff --git a/bot_modules/authorize.py b/bot_modules/authorize.py new file mode 100644 index 0000000..02e4763 --- /dev/null +++ b/bot_modules/authorize.py @@ -0,0 +1,397 @@ +# -*- coding: utf8 -*- +# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) + +# Авторизация или регистрация в кооперативе или другой организации + +from bot_sys import bot_bd, keyboard, user_access, bd_table, bot_subscribes, config +from bot_modules import mod_table_operate, mod_simple_message, users_groups_agregator, groups_utils +from template import docs_message, bd_item, bd_item_select + +from enum import Enum +from enum import auto +# --------------------------------------------------------- +# БД +module_name = 'authorize' + +table_name = module_name +user_id_field = 'userID' +user_name_field = 'userName' +user_family_name_field = 'userFamilyName' +user_middle_name_field = 'userMiddleName' +user_birthday_field = 'userBirthday' +user_address_field = 'userAddress' +user_contacts_field = 'userContacts' +user_confirm_field = 'userConfirm' +user_auth_docs_field = 'authDocs' +user_photo_pay_field = 'photoPay' +access_field = 'authorizeAccess' +create_datetime_field = 'authorizeCreateDateTime' + +user_id_table_field = bd_table.TableField(user_id_field, bd_table.TableFieldDestiny.USER_ID, bd_table.TableFieldType.INT) + +class ConfirmStatus(Enum): + YES = auto() + NO = auto() + +table = bd_table.Table(table_name, [ + user_id_table_field, + bd_table.TableField(user_name_field, bd_table.TableFieldDestiny.USER_NAME, bd_table.TableFieldType.STR), + bd_table.TableField(user_family_name_field, bd_table.TableFieldDestiny.USER_FAMILY_NAME, bd_table.TableFieldType.STR), + bd_table.TableField(user_middle_name_field, bd_table.TableFieldDestiny.USER_MIDDLE_NAME, bd_table.TableFieldType.STR), + bd_table.TableField(user_birthday_field, bd_table.TableFieldDestiny.USER_BIRTHDAY, bd_table.TableFieldType.STR), + bd_table.TableField(user_address_field, bd_table.TableFieldDestiny.USER_ADDRESS, bd_table.TableFieldType.STR), + bd_table.TableField(user_contacts_field, bd_table.TableFieldDestiny.USER_CONTACTS, bd_table.TableFieldType.STR), + bd_table.TableField(user_confirm_field, bd_table.TableFieldDestiny.USER_CONFIRM, bd_table.TableFieldType.ENUM, a_Enum = ConfirmStatus), + bd_table.TableField(user_auth_docs_field, bd_table.TableFieldDestiny.AUTH_PHOTO_DOCS, bd_table.TableFieldType.PHOTO), + bd_table.TableField(user_photo_pay_field, bd_table.TableFieldDestiny.PHOTO_PAY, bd_table.TableFieldType.PHOTO), + 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), + ] + , + [ + [user_id_table_field], + ] + ) + +init_access = f'{user_access.user_access_group_new}=vea' +def_init_access = f'{user_access.user_access_group_new}=a' + +def GetAuthorizeItem(a_Bot, a_UserID): + items = bd_item.GetBDItemsTemplate(a_Bot, table_name, user_id_field)(a_UserID) + if len(items) == 1: + return items[0] + return None + +# --------------------------------------------------------- +# Сообщения и кнопки + +class ButtonNames(Enum): + LIST_AUTH_DOCS = auto() + +button_names = { + mod_simple_message.ButtonNames.START: "🔑 Авторизация", + mod_table_operate.ButtonNames.LIST: "≣ Список авторизаций пользователей", + mod_table_operate.ButtonNames.ADD: "📨 Заявка на вступление", + ButtonNames.LIST_AUTH_DOCS: "📨 Регистрационные документы", + mod_table_operate.ButtonNames.EDIT: "🛠 Редактировать свои данные", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_ID): "☐ Изменить id пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_NAME): "☐ Изменить имя пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_FAMILY_NAME): "☐ Изменить фамилию пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_MIDDLE_NAME): "☐ Изменить отчество пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_BIRTHDAY): "☐ Изменить дату рождения пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_ADDRESS): "☐ Изменить адрес пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_CONTACTS): "☐ Изменить контакты пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_CONFIRM): "☐ Изменить подтверждение пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.USER_ID): "☐ Изменить id пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.ACCESS): "✋ Доступ к авторизации пользователя", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.AUTH_PHOTO_DOCS): "☐ Загрузить подписанные документы", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.PHOTO_PAY): "☐ Оплатить членский взнос", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.ACCESS): "✋ Доступ к авторизации пользователя", + mod_table_operate.ButtonNames.DEL: "❌ Удалить авторизацию пользователя", + mod_table_operate.EnumButton(ConfirmStatus.YES): "Да, все данные верны", + mod_table_operate.EnumButton(ConfirmStatus.NO): "Нет, данные не верны", +} + +class Messages(Enum): + LIST_AUTH_DOCS = auto() + LIST_AUTH_DOCS_ERROR = auto() + +messages = { + mod_simple_message.Messages.START: f''' +{button_names[mod_simple_message.ButtonNames.START]} + +''', + Messages.LIST_AUTH_DOCS: ''' +ваши регистрационные документы: +''', + Messages.LIST_AUTH_DOCS_ERROR: ''' +Ошибка получения документов. Обратитесь в техподдержку. +''', + mod_table_operate.Messages.SELECT: ''' +Пожалуйста, выберите пользователя: +''', + mod_table_operate.Messages.ERROR_FIND: ''' +❌ Ошибка, пользователь не найден +''', + mod_table_operate.Messages.OPEN: f''' +Пользователь: #{user_id_field} + +Имя: #{user_name_field} +Фамилия: #{user_family_name_field} +Отчество: #{user_middle_name_field} +Дата рождения: #{user_birthday_field} +Адрес: #{user_address_field} +Контакты: #{user_contacts_field} +Подтверждение авторизации: #{user_confirm_field} + +Время создания: #{create_datetime_field} +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.USER_NAME): ''' +Авторизация. Шаг №1 + +Введите своё имя: +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.USER_FAMILY_NAME): ''' +Авторизация. Шаг №2 + +Введите свою фамилию: +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.USER_MIDDLE_NAME): ''' +Авторизация. Шаг №3 + +Введите своё отчество: +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.USER_BIRTHDAY): ''' +Авторизация. Шаг №4 + +Введите свою дату рождения в формате ДД.ММ.ГГГГ: +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.USER_ADDRESS): ''' +Авторизация. Шаг №5 + +Введите свой домашний адрес: +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.USER_CONTACTS): ''' +Авторизация. Шаг №6 + +Введите свои контакты: +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.USER_CONFIRM): f''' +Авторизация. Шаг №7 + +Имя: #{user_name_field} +Фамилия: #{user_family_name_field} +Отчество: #{user_middle_name_field} +Дата рождения: #{user_birthday_field} +Адрес: #{user_address_field} +Контакты: #{user_contacts_field} +Подтверждение авторизации: #{user_confirm_field} + +Подтвердите свои данные: +''', + + mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Вы успешно зарегистрированы! Посмотрите документы и отправьте фотографии подписанных документов''', + mod_table_operate.Messages.START_EDIT: ''' +Пожалуйста, выберите действие: +''', + mod_table_operate.Messages.SELECT_TO_EDIT: ''' +Выберите пользователя, у которого вы хотите отредактировать данные. +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.USER_NAME): f''' +Текущее имя пользователя: +#{user_name_field} + +Введите новое имя пользователя: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.USER_FAMILY_NAME): f''' +Текущая фамилия пользователя: +#{user_family_name_field} + +Введите новую фамилию пользователя: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.USER_MIDDLE_NAME): f''' +Текущее отчество пользователя: +#{user_middle_name_field} + +Введите новое отчество пользователя: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.USER_BIRTHDAY): f''' +Текущая дата рождения пользователя: +#{user_birthday_field} + +Введите новую дату рождения пользователя: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.USER_ADDRESS): f''' +Текущий адрес пользователя: +#{user_address_field} + +Введите новый адрес пользователя: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.USER_CONTACTS): f''' +Текущие контакты пользователя: +#{user_contacts_field} + +Введите новые контакты пользователя: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.USER_CONFIRM): f''' +Текущее подтвержение пользователя: +#{user_confirm_field} + +Введите новое подтверждение пользователя: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.AUTH_PHOTO_DOCS): f''' +Загрузите подписанный документ: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.PHOTO_PAY): f''' +Загрузите чек по оплате ЧВ: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.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: '''✅ Данные пользователя успешно удалены!''', +} + +messages_subscribes = { + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD):f'''Данные по авторизации созданы''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT):f'''Данные по авторизации отредактированы''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL):f'''Данные по авторизации удалены''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_EDIT):f'''Данные по авторизации отредактированы #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_DEL):f'''Данные по авторизации удалены #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT):f'''Данные по авторизации созданы''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT):f'''Данные по авторизации отредактированы''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT):f'''Данные по авторизации удалены''', +} + +messages.update(messages_subscribes) + +messages_confirm_status = { + mod_table_operate.EnumMessageForView(ConfirmStatus.YES): f'''Да, все данные верны''', + mod_table_operate.EnumMessageForView(ConfirmStatus.NO): f'''Нет, данные не верны''', +} + +messages.update(messages_confirm_status) + +class ModuleAuthorize(mod_table_operate.TableOperateModule): + def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, def_init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + + def GetName(self): + return module_name + + def GetAccessForEditKeyboardButtons(self, a_Field): + cur_dict = { + bd_table.TableFieldDestiny.USER_ID: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_FAMILY_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_MIDDLE_NAME: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_BIRTHDAY: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_ADDRESS: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_CONTACTS: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.USER_CONFIRM: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.ACCESS: user_access.AccessMode.NONE, + bd_table.TableFieldDestiny.AUTH_PHOTO_DOCS: user_access.AccessMode.ADD, + bd_table.TableFieldDestiny.PHOTO_PAY: user_access.AccessMode.ADD, + } + return cur_dict.get(a_Field.m_Destiny, super().GetAccessForEditKeyboardButtons(a_Field)) + + def GetButtonNameAndKeyValueAndAccess(self, a_Item): + key_name_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_ID) + name_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_NAME) + fam_name_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_FAMILY_NAME) + access_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS) + assert key_name_id != None + assert name_field_id != None + assert fam_name_field_id != None + assert access_field_id != None + return \ + a_Item[name_field_id] + ' ' + a_Item[fam_name_field_id] + '(' + str(a_Item[key_name_id]) +')',\ + a_Item[key_name_id],\ + a_Item[access_field_id] + + async def OnChangeField(self, a_Field, a_ItemID, a_ItemData, a_EditUserID): + super().OnChangeField(a_Field, a_ItemID, a_ItemData, a_EditUserID) + user_id_field_name = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.USER_ID) + user_id = a_ItemData[user_id_field_name] + user_confirm_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_CONFIRM) + auth_docs_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.AUTH_PHOTO_DOCS) + pay_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.PHOTO_PAY) + item = GetAuthorizeItem(self.m_Bot, user_id) + if item and item[user_confirm_field_id] != '' and item[auth_docs_field_id] != '' and item[pay_field_id] != '': + users_groups_agregator.AddUserInGroup(self.m_Bot, user_id, user_access.user_access_group_auth_users) + + def GetStartButtons(self, a_Message, a_UserGroups): + user_id = str(a_Message.from_user.id) + item = GetAuthorizeItem(self.m_Bot, user_id) + user_confirm_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.USER_CONFIRM) + + cur_buttons = [] + + if item and item[user_confirm_field_id] == self.GetMessage(mod_table_operate.EnumMessageForView(ConfirmStatus.YES)).GetDesc(): + cur_buttons += [[ButtonNames.LIST_AUTH_DOCS, user_access.AccessMode.VIEW]] + cur_buttons += [[mod_table_operate.EditButton(bd_table.TableFieldDestiny.AUTH_PHOTO_DOCS), user_access.AccessMode.VIEW]] + cur_buttons += [[mod_table_operate.EditButton(bd_table.TableFieldDestiny.PHOTO_PAY), user_access.AccessMode.VIEW]] + else: + cur_buttons += [[mod_table_operate.ButtonNames.ADD, user_access.AccessMode.ADD]] + + return cur_buttons + [ + [mod_table_operate.ButtonNames.LIST, user_access.AccessMode.VIEW], + [mod_table_operate.ButtonNames.DEL, user_access.AccessMode.DELETE], + [mod_table_operate.ButtonNames.EDIT, user_access.AccessMode.EDIT], + ] + + def RegisterHandlers(self): + super().RegisterHandlers() + + def GetFilesFunc(a_user_id): + files = GetAuthDocs() + cur_dict = GetReplaceDictFunc(self.m_Bot, a_user_id) + result = {} + for f in files: + result.update({f: cur_dict}) + + return result + + button_name = self.GetButton(ButtonNames.LIST_AUTH_DOCS) + if button_name: + self.m_Bot.RegisterMessageHandler( + docs_message.DocFilesTemplate( + self.m_Bot, + GetFilesFunc, + self.GetMessage(Messages.LIST_AUTH_DOCS), + self.m_GetAccessFunc, + self.m_GetStartKeyboardButtonsFunc, + None, + self.GetMessage(Messages.LIST_AUTH_DOCS_ERROR), + access_mode = user_access.AccessMode.VIEW + ), + bd_item.GetCheckForTextFunc(button_name) + ) + + def AddBDItemFunc(self, a_ItemData, a_UserID): + a_ItemData[user_id_field] = a_UserID + a_ItemData[user_auth_docs_field] = '' + a_ItemData[user_photo_pay_field] = '' + result = super().AddBDItemFunc(a_ItemData, a_UserID) + return result + + def GetKeyFieldDestiny(self): + return bd_table.TableFieldDestiny.USER_ID + + def GetInitBDCommands(self): + return super(). GetInitBDCommands() + [ + groups_utils.CreateGroupRequest(user_access.user_access_group_auth_users) + ] + +def GetReplaceDictFunc(a_Bot, a_user_id): + item = GetAuthorizeItem(a_Bot, a_user_id) + if not item: + return None + result = {} + i = 0 + for f in table.GetFields(): + result.update({str(f.m_Destiny): str(item[i])}) + i += 1 + print(result) + return result + +auth_docs_file_name = 'config_auth_docs' + +g_auth_docs = [] + +def GetAuthDocs(): + global g_auth_docs + if len(g_auth_docs) == 0: + root_ids = config.GetAllLinesFromFile(auth_docs_file_name) + for i in root_ids: + g_auth_docs += [config.ClearReadLine(i)] + + return g_auth_docs diff --git a/bot_modules/backup.py b/bot_modules/backup.py index cf294a2..dc7b989 100644 --- a/bot_modules/backup.py +++ b/bot_modules/backup.py @@ -48,7 +48,7 @@ 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_BotSubscribes, a_Log): - super().__init__(messages, button_names, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(messages, button_names, init_access, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) self.m_BackupBDButtonName = self.CreateButton('backup bd', backup_bd_button_name) self.m_BackupBDMessage = self.CreateMessage('backup bd', backup_bd_message) diff --git a/bot_modules/bd_version.py b/bot_modules/bd_version.py new file mode 100644 index 0000000..2d5eff5 --- /dev/null +++ b/bot_modules/bd_version.py @@ -0,0 +1,51 @@ +# -*- coding: utf8 -*- +# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) + +# Версия БД +# Этот модуль нужен для того, чтобы проводить миграции на новую версию. Он записывает в БД номер текущей версии. + + +from bot_sys import bot_bd, keyboard, user_access, bd_table, bot_subscribes +from bot_modules import mod_table_operate, mod_simple_message + +# --------------------------------------------------------- +# БД +module_name = 'bd_version' + +table_name = module_name +base_version_number_field = 'baseVersionNumber' +sub_version_number_field = 'subVersionNumber' + +table_base_version_number_field = bd_table.TableField(base_version_number_field, bd_table.TableFieldDestiny.VERSION_NUMBER, bd_table.TableFieldType.INT) +table_sub_version_number_field = bd_table.TableField(sub_version_number_field, bd_table.TableFieldDestiny.SUB_VERSION_NUMBER, bd_table.TableFieldType.INT) + +table = bd_table.Table(table_name, [ + table_base_version_number_field, + table_sub_version_number_field, + ], + [ + [table_base_version_number_field, table_sub_version_number_field], + ]) + +init_access = f'{user_access.user_access_group_new}=-' + +# --------------------------------------------------------- +# Сообщения и кнопки + +button_names = { +} + +messages = { +} + +class ModuleBDVersion(mod_table_operate.TableOperateModule): + def __init__(self, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): + super().__init__(table, messages, button_names, None, None, init_access, init_access, None, None, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + + def GetName(self): + return module_name + + def GetInitBDCommands(self): + return super(). GetInitBDCommands() + [ + f"INSERT OR IGNORE INTO {table_name} ({base_version_number_field}, {sub_version_number_field}) VALUES ('{1}', '{1}');" + ] diff --git a/bot_modules/buttons.py b/bot_modules/buttons.py index 63e77fa..09dbfda 100644 --- a/bot_modules/buttons.py +++ b/bot_modules/buttons.py @@ -128,7 +128,7 @@ messages = { 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_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/comments.py b/bot_modules/comments.py index 953169f..6f6be15 100644 --- a/bot_modules/comments.py +++ b/bot_modules/comments.py @@ -119,18 +119,21 @@ messages = { } messages_subscribes = { - mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ADD):f'''Комментарий создан''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD):f'''Комментарий создан''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT):f'''Комментарий отредактирован''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL):f'''Комментарий удалён''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_EDIT):f'''Комментарий отредактирован #item_id''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_DEL):f'''Комментарий удалён #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT):f'''Комментарий создан''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT):f'''Комментарий отредактирован''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT):f'''Комментарий удалён''', } messages.update(messages_subscribes) 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_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/groups.py b/bot_modules/groups.py index c82485c..4e10654 100644 --- a/bot_modules/groups.py +++ b/bot_modules/groups.py @@ -125,12 +125,12 @@ messages = { class ModuleGroups(mod_table_operate.TableOperateModule): def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name def GetInitBDCommands(self): return super(). GetInitBDCommands() + [ - f"INSERT OR IGNORE INTO {table_name} ({name_field}, {access_field}, {create_datetime_field}) VALUES ('{user_access.user_access_group_new}', '{user_access.user_access_group_new}=-', {bot_bd.GetBDDateTimeNow()});" + groups_utils.CreateGroupRequest(user_access.user_access_group_new) ] diff --git a/bot_modules/groups_utils.py b/bot_modules/groups_utils.py index 1bc67a0..27b2bbe 100644 --- a/bot_modules/groups_utils.py +++ b/bot_modules/groups_utils.py @@ -3,7 +3,7 @@ # Группы пользователей -from bot_sys import user_access +from bot_sys import user_access, bot_bd table_name = 'user_groups' key_name = 'groupID' @@ -28,3 +28,7 @@ def GetUserGroupData(a_Bot, a_UserID): if len(i) > 0: groups += [i[0]] return user_access.UserGroups(a_UserID, groups) + +def CreateGroupRequest(a_GroupName): + return f"INSERT OR IGNORE INTO {table_name} ({name_field}, {access_field}, {create_datetime_field}) VALUES ('{a_GroupName}', '{user_access.user_access_group_new}=-', {bot_bd.GetBDDateTimeNow()});" + diff --git a/bot_modules/languages.py b/bot_modules/languages.py index 06d0835..b3022fb 100644 --- a/bot_modules/languages.py +++ b/bot_modules/languages.py @@ -126,7 +126,7 @@ messages = { 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_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) self.m_LanguageIDs = {} def GetName(self): diff --git a/bot_modules/messages.py b/bot_modules/messages.py index 310b043..27ca51f 100644 --- a/bot_modules/messages.py +++ b/bot_modules/messages.py @@ -128,7 +128,7 @@ messages = { 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_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/mod_simple_message.py b/bot_modules/mod_simple_message.py index 0221977..8f5e9a3 100644 --- a/bot_modules/mod_simple_message.py +++ b/bot_modules/mod_simple_message.py @@ -17,9 +17,10 @@ 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_BotSubscribes, a_Log): + def __init__(self, a_Messages, a_Buttons, a_InitAccess, a_DefInitAccess, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): self.m_ChildModuleNameList = a_ChildModuleNameList self.m_InitAccess = a_InitAccess + self.m_DefInitAccess = a_DefInitAccess self.m_Bot = a_Bot self.m_ModuleAgregator = a_ModuleAgregator self.m_BotMessages = a_BotMessages @@ -84,6 +85,8 @@ class SimpleMessageModule(mod_interface.IModule): def GetButtons(self, a_ModNameList): buttons = [] + if not a_ModNameList: + return buttons for n in a_ModNameList: m = self.m_ModuleAgregator.GetModule(n) b = m.GetModuleButtons() @@ -97,7 +100,7 @@ class SimpleMessageModule(mod_interface.IModule): def GetInitBDCommands(self): return [ - access_utils.GetAccessForModuleRequest(self.GetName(), self.m_InitAccess, self.m_InitAccess), + access_utils.GetAccessForModuleRequest(self.GetName(), self.m_InitAccess, self.m_DefInitAccess), ] def GetAccess(self): diff --git a/bot_modules/mod_table_operate.py b/bot_modules/mod_table_operate.py index acff162..4188812 100644 --- a/bot_modules/mod_table_operate.py +++ b/bot_modules/mod_table_operate.py @@ -51,6 +51,12 @@ class Messages(Enum): SELECT_TO_DELETE = auto() SUCCESS_DELETE = auto() +def GetCurItem(a_Bot, a_TableName, a_KeyName, a_KeyValue): + items = bd_item.GetBDItemsTemplate(a_Bot, a_TableName, a_KeyName)(a_KeyValue) + if len(items) == 1: + return items[0] + return None + create_fsm_create_cmd = ''' class FSMCreate{a_ModName}(StatesGroup): {items} @@ -83,8 +89,8 @@ def MakeFSMForEdit(a_ModName, a_FieldName): return _locals['fsm'] class TableOperateModule(mod_simple_message.SimpleMessageModule): - def __init__(self, a_Table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(a_Messages, a_Buttons, a_InitAccess, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + def __init__(self, a_Table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_DefInitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): + super().__init__(a_Messages, a_Buttons, a_InitAccess, a_DefInitAccess, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) self.m_Table = a_Table self.m_EditModuleNameList = a_EditModuleNameList self.m_ChildModName = a_ChildModName @@ -99,8 +105,8 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): return self.GetButtonNameAndKeyValueAndAccess(a_Item) self.m_GetButtonNameAndKeyValueAndAccessFunc = GetButtonNameAndKeyValueAndAccess - async def PreDelete(a_CallbackQuery, a_Item): - return await self.PreDelete(a_CallbackQuery, a_Item) + async def PreDelete(a_CallbackQuery, a_Item, a_None, table_name = self.m_Table.GetName()): + return await self.PreDelete(a_CallbackQuery, a_Item, a_None) self.m_PreDeleteFunc = PreDelete async def PostDelete(a_CallbackQuery, a_ItemID): @@ -116,23 +122,33 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): self.m_Table.GetInitTableRequest(), ] + super().GetInitBDCommands() + def GetStartButtons(self, a_Message, a_UserGroups): + return [ + [ButtonNames.LIST, user_access.AccessMode.VIEW], + [ButtonNames.ADD, user_access.AccessMode.ADD], + [ButtonNames.DEL, user_access.AccessMode.DELETE], + [ButtonNames.EDIT, user_access.AccessMode.EDIT], + ] + 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()), - ] + cur_buttons = [] + for b in self.GetStartButtons(a_Message, a_UserGroups): + bn = b[0] + ba = b[1] + cur_buttons += [keyboard.ButtonWithAccess(self.GetButton(bn), ba, self.GetAccess())] return mod_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups) + def GetAccessForEditKeyboardButtons(self, a_Field): + if a_Field.m_Destiny == bd_table.TableFieldDestiny.ACCESS or a_Field.m_Destiny == bd_table.TableFieldDestiny.DEFAULT_ACCESS: + return user_access.AccessMode.ACCEES_EDIT + return user_access.AccessMode.EDIT + def GetEditKeyboardButtons(self, a_Message, a_UserGroups): mod_buttons = keyboard.MakeButtons(self.m_Bot, self.GetButtons(self.m_EditModuleNameList), a_UserGroups) cur_buttons = [] for f in self.m_Table.GetFields(): - access = user_access.AccessMode.EDIT - if f.m_Destiny == bd_table.TableFieldDestiny.ACCESS or f.m_Destiny == bd_table.TableFieldDestiny.DEFAULT_ACCESS: - access = user_access.AccessMode.ACCEES_EDIT + access = self.GetAccessForEditKeyboardButtons(f) cur_buttons += [keyboard.ButtonWithAccess(self.GetButton(EditButton(f.m_Destiny)), access, self.GetAccess()),] return mod_buttons + keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups) @@ -154,7 +170,7 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): return keyboard.MakeInlineKeyboardButtons(self.m_Bot, cur_buttons, a_UserGroups) def GetButtonNameAndKeyValueAndAccess(self, a_Item): - key_name_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.KEY) + key_name_id = self.GetKeyFieldID() name_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.NAME) access_field_id = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS) assert key_name_id != None @@ -182,13 +198,34 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): a_Msg.UpdatePhotoID(','.join(photos)) return a_Msg + def UpdateMessageByDict(self, a_Msg, a_Lang, a_ItemDict, a_EnablePhoto = False): + a_Msg.UpdateDesc(self.m_Table.ReplaceAllFieldTagsByDict(a_Msg.GetDesc(), a_ItemDict)) + photos = [] + for f in self.m_Table.GetFields(): + if f.m_Type == bd_table.TableFieldType.ENUM: + for s in f.m_Enum: + msg = self.GetMessage(EnumMessageForView(s)) + if msg: + a_Msg.UpdateDesc(a_Msg.GetDesc().replace(str(s), str(msg.GetMessageForLang(a_Lang).StaticCopy()))) + elif f.m_Type == bd_table.TableFieldType.PHOTO: + if f.m_Name in a_ItemDict: + photos += [str(a_ItemDict[f.m_Name])] + if a_EnablePhoto: + a_Msg.UpdatePhotoID(','.join(photos)) + return a_Msg + def ShowMessageTemplate(self, a_Message, Inline_keyboard_template_func = None, a_EnablePhoto = False): - async def ShowMessage(a_CallbackQuery, a_Item): + async def ShowMessage(a_CallbackQuery, a_Item, a_ItemDict, table_name = self.m_Table.GetName()): msg = a_Message.StaticCopy() - # TODO: добавить поддержку языка в a_MessageName + # TODO: добавить поддержку языков в a_MessageName Inline_keyboard_func = None item_access = None - if a_Item: + if a_ItemDict: + lang = str(a_CallbackQuery.from_user.language_code) + msg = msg.GetMessageForLang(lang).StaticCopy() + msg = self.UpdateMessageByDict(msg, lang, a_ItemDict, a_EnablePhoto = a_EnablePhoto) + + if a_Item and self.m_Table.GetName() == table_name: 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(): @@ -197,14 +234,14 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): msg = self.UpdateMessage(msg, lang, a_Item, a_EnablePhoto = a_EnablePhoto) 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)]) + Inline_keyboard_func = Inline_keyboard_template_func(a_Item[self.GetKeyFieldID()]) return simple_message.WorkFuncResult(msg, item_access = item_access, Inline_keyboard_func = Inline_keyboard_func) return ShowMessage - async def PreDelete(self, a_CallbackQuery, a_Item): + async def PreDelete(self, a_CallbackQuery, a_Item, a_None): if len(a_Item) < self.m_Table.GetFieldsCount(): - return simple_message.WorkFuncResult(error_find_proj_message) + return simple_message.WorkFuncResult(self.GetMessage(Messages.ERROR_FIND)) access = a_Item[self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.ACCESS)] return simple_message.WorkFuncResult(self.GetMessage(Messages.SUCCESS_DELETE), None, item_access = access) @@ -222,6 +259,18 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): item_id = a_ItemID await self.SendSubscribe(subscribe_type, item_id, user_id) + table_name = self.m_Table.GetName() + key_name = self.GetKeyFieldName() + + cur_item = GetCurItem(self.m_Bot, table_name, key_name, a_ItemID) + print(cur_item) + + parent_id_field_index = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.PARENT_ID) + if parent_id_field_index and cur_item and cur_item[parent_id_field_index]: + subscribe_type = bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT + item_id = cur_item[parent_id_field_index] + await self.SendSubscribe(subscribe_type, item_id, user_id) + return simple_message.WorkFuncResult(self.GetMessage(Messages.SUCCESS_DELETE)) async def AddBDItemFunc(self, a_ItemData, a_UserID): @@ -265,10 +314,15 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): else: self.m_Log.Success(f'Пользователь {a_UserID}. Добавлена запись в таблицу {request} {param}.') - subscribe_type = bot_subscribes.SubscribeType.ADD + subscribe_type = bot_subscribes.SubscribeType.ANY_ITEM_ADD item_id = -1 await self.SendSubscribe(subscribe_type, item_id, a_UserID) + if parent_id_field and a_ItemData[parent_id_field]: + subscribe_type = bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT + item_id = a_ItemData[parent_id_field] + await self.SendSubscribe(subscribe_type, item_id, a_UserID) + return res, error async def SendSubscribe(self, a_Type, a_ItemID, a_OwnerUserID): @@ -286,7 +340,10 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): a_Message = None user_groups = None parse_mode = None - await simple_message.SendMessage(self.m_Bot, a_BotMessage, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_UserID, a_Message, user_groups, parse_mode=parse_mode) + try: + await simple_message.SendMessage(self.m_Bot, a_BotMessage, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_UserID, a_Message, user_groups, parse_mode=parse_mode) + except: + return def SelectSourceTemplate(self, a_PrevPrefix, a_ButtonName): parent_id_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PARENT_ID) @@ -309,12 +366,12 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): return a_Prefix - def AdditionalKeyboardForEditTemplate(self, a_Field): + def AdditionalKeyboardForEditTemplate(self, a_Field, user_access = user_access.AccessMode.EDIT): if a_Field.m_Type == bd_table.TableFieldType.ENUM: def KeyboardButtons(a_Message, a_UserGroups): cur_buttons = [] for s in a_Field.m_Enum: - cur_buttons += [keyboard.ButtonWithAccess(self.GetButton(EnumButton(s)), user_access.AccessMode.EDIT, self.GetAccess()),] + cur_buttons += [keyboard.ButtonWithAccess(self.GetButton(EnumButton(s)), user_access, self.GetAccess()),] return keyboard.MakeButtons(self.m_Bot, cur_buttons, a_UserGroups) return KeyboardButtons return None @@ -339,6 +396,18 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): await self.SendSubscribe(subscribe_type, item_id, a_EditUserID) + table_name = self.m_Table.GetName() + key_name = self.GetKeyFieldName() + + cur_item = GetCurItem(self.m_Bot, table_name, key_name, a_ItemID) + print(cur_item) + + parent_id_field_index = self.m_Table.GetFieldIDByDestiny(bd_table.TableFieldDestiny.PARENT_ID) + if parent_id_field_index and cur_item and cur_item[parent_id_field_index]: + subscribe_type = bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT + item_id = cur_item[parent_id_field_index] + await self.SendSubscribe(subscribe_type, item_id, a_EditUserID) + def RegisterEdit(self, a_Field, a_AccessMode = user_access.AccessMode.EDIT): a_ButtonName = self.GetButton(EditButton(a_Field.m_Destiny)) a_EditMessage = self.GetMessage(EditMessage(a_Field.m_Destiny)) @@ -356,12 +425,12 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): return self.OnChange() table_name = self.m_Table.GetName() - key_name = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.KEY) + key_name = self.GetKeyFieldName() edit_keyboard_func = self.m_GetEditKeyboardButtonsFunc GetButtonNameAndKeyValueAndAccess = self.m_GetButtonNameAndKeyValueAndAccessFunc GetAccess = self.m_GetAccessFunc - a_Prefix = self.RegisterSelect(a_ButtonName, a_AccessMode, only_parent = True) + a_Prefix = self.RegisterSelect(a_ButtonName, user_access.AccessMode.VIEW, only_parent = True) bd_item_edit.EditBDItemRegisterHandlers(self.m_Bot, \ self.SelectSourceTemplate(a_Prefix, a_ButtonName), \ @@ -383,9 +452,23 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): ) def GetAddFields(self): + add_destiny = ( + bd_table.TableFieldDestiny.NAME, + bd_table.TableFieldDestiny.DESC, + bd_table.TableFieldDestiny.PHOTO, + bd_table.TableFieldDestiny.SUBSCRIBE_TYPE, + bd_table.TableFieldDestiny.ITEM_ID, + bd_table.TableFieldDestiny.USER_NAME, + bd_table.TableFieldDestiny.USER_FAMILY_NAME, + bd_table.TableFieldDestiny.USER_MIDDLE_NAME, + bd_table.TableFieldDestiny.USER_BIRTHDAY, + bd_table.TableFieldDestiny.USER_ADDRESS, + bd_table.TableFieldDestiny.USER_CONTACTS, + bd_table.TableFieldDestiny.USER_CONFIRM, + ) fields = [] for f in self.m_Table.GetFields(): - if f.m_Destiny in (bd_table.TableFieldDestiny.NAME, bd_table.TableFieldDestiny.DESC, bd_table.TableFieldDestiny.PHOTO, bd_table.TableFieldDestiny.SUBSCRIBE_TYPE, bd_table.TableFieldDestiny.ITEM_ID, ): + if f.m_Destiny in add_destiny: fields += [f] return fields @@ -419,23 +502,32 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): f_id = 0 f = fields[f_id] - keyboard = bd_item.MixKeyboardFuncTemplate(self.AdditionalKeyboardForEditTemplate(f), GetKeyboard(f)) + keyboard = bd_item.MixKeyboardFuncTemplate(self.AdditionalKeyboardForEditTemplate(f, user_access.AccessMode.ADD), GetKeyboard(f)) reg_func(bd_item_add.StartAddBDItemTemplate(self.m_Bot, fsm, getattr(fsm, f'item{f_id}'), self.ShowMessageTemplate(self.GetMessage(CreateMessage(f.m_Destiny))), a_ParentTableName, a_ParentKeyFieldName, a_ParentPrefix, a_AccessFunc, keyboard, a_ButtonFunc, access_mode), a_StartCheckFunc) for i in range(len(fields) - 1): f = fields[i] next_f = fields[i + 1] - keyboard = bd_item.MixKeyboardFuncTemplate(self.AdditionalKeyboardForEditTemplate(next_f), GetKeyboard(next_f)) + keyboard = bd_item.MixKeyboardFuncTemplate(self.AdditionalKeyboardForEditTemplate(next_f, user_access.AccessMode.ADD), GetKeyboard(next_f)) self.m_Bot.RegisterMessageHandler(bd_item_add.NextAddBDItemTemplate(self.m_Bot, fsm, None, a_ParentTableName, a_ParentKeyFieldName, f.m_Name, self.ShowMessageTemplate(self.GetMessage(CreateMessage(next_f.m_Destiny))), None, a_AccessFunc, keyboard, a_ButtonFunc, access_mode, field_type = GetFieldType(f)), content_types = GetContentTypes(f), state = getattr(fsm, f'item{i}')) f_id = len(fields) - 1 f = fields[f_id] self.m_Bot.RegisterMessageHandler(bd_item_add.FinishAddBDItemTemplate(self.m_Bot, fsm, a_AddBDItemFunc, a_ParentTableName, a_ParentKeyFieldName, f.m_Name, self.ShowMessageTemplate(self.GetMessage(Messages.SUCCESS_CREATE)), None, a_AccessFunc, a_ButtonFunc, access_mode, field_type = GetFieldType(f)), content_types = GetContentTypes(f), state = getattr(fsm, f'item{f_id}')) + def GetKeyFieldDestiny(self): + return bd_table.TableFieldDestiny.KEY + + def GetKeyFieldName(self): + return self.m_Table.GetFieldNameByDestiny(self.GetKeyFieldDestiny()) + + def GetKeyFieldID(self): + return self.m_Table.GetFieldIDByDestiny(self.GetKeyFieldDestiny()) + def RegisterHandlers(self): super().RegisterHandlers() table_name = self.m_Table.GetName() - key_name = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.KEY) + key_name = self.GetKeyFieldName() 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) @@ -448,7 +540,7 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): 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) + parent_key_name = parent_mod.GetKeyFieldName() def GetViewItemInlineKeyboardTemplate(a_ItemID): return self.GetViewItemInlineKeyboardTemplate(a_ItemID) @@ -483,7 +575,7 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): # Удаление a_ButtonName = self.GetButton(ButtonNames.DEL) if a_ButtonName: - a_Prefix = self.RegisterSelect(a_ButtonName, user_access.AccessMode.DELETE) + a_Prefix = self.RegisterSelect(a_ButtonName, user_access.AccessMode.VIEW) bd_item_delete.DeleteBDItemRegisterHandlers(self.m_Bot, \ a_Prefix, \ table_name, \ @@ -497,7 +589,7 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule): # Добавление a_ButtonName = self.GetButton(ButtonNames.ADD) if a_ButtonName: - a_Prefix = self.RegisterSelect(a_ButtonName, user_access.AccessMode.ADD, only_parent = True) + a_Prefix = self.RegisterSelect(a_ButtonName, user_access.AccessMode.VIEW, only_parent = True) check_func = bd_item.GetCheckForTextFunc(a_ButtonName) if a_Prefix: diff --git a/bot_modules/needs.py b/bot_modules/needs.py index 0f0bf2f..0bba8ba 100644 --- a/bot_modules/needs.py +++ b/bot_modules/needs.py @@ -120,18 +120,21 @@ messages = { } messages_subscribes = { - mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ADD):f'''Потребность создана''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD):f'''Потребность создана''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT):f'''Потребность отредактирована''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL):f'''Потребность удалёна''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_EDIT):f'''Потребность отредактирована #item_id''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_DEL):f'''Потребность удалёна #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT):f'''Потребность создана''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT):f'''Потребность отредактирована''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT):f'''Потребность удалёна''', } messages.update(messages_subscribes) 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_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/orders.py b/bot_modules/orders.py index 3559006..1f8ecdb 100644 --- a/bot_modules/orders.py +++ b/bot_modules/orders.py @@ -22,6 +22,7 @@ module_name = 'orders' table_name = module_name key_name = 'orderID' +user_id_field = 'userID' name_field = 'orderName' desc_field = 'orderDesc' photo_field = 'orderPhoto' @@ -30,10 +31,11 @@ status_field = 'orderStatus' address_field = 'orderAddress' access_field = 'orderAccess' create_datetime_field = 'orderCreateDateTime' -parent_id_field = 'userID' +parent_id_field = 'catID' table = bd_table.Table(table_name, [ bd_table.TableField(key_name, bd_table.TableFieldDestiny.KEY, bd_table.TableFieldType.INT), + bd_table.TableField(user_id_field, bd_table.TableFieldDestiny.USER_ID, 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.PHOTO), @@ -45,7 +47,7 @@ table = bd_table.Table(table_name, [ bd_table.TableField(parent_id_field, bd_table.TableFieldDestiny.PARENT_ID, bd_table.TableFieldType.INT), ]) -init_access = f'{user_access.user_access_group_new}=vea' +init_access = f'{user_access.user_access_group_auth_users}=vea' # --------------------------------------------------------- # Сообщения и кнопки @@ -134,7 +136,7 @@ messages = { ''', mod_table_operate.EditMessage(bd_table.TableFieldDestiny.ADDRESS): f''' Текущий адрес заказа: -#{desc_field} +#{address_field} Введите новый адрес доставки заказа (укажите, кто, когда и где его сможет забрать): ''', @@ -164,26 +166,31 @@ messages_order_status = { messages.update(messages_order_status) messages_subscribes = { - mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ADD):f'''Заказ создан''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD):f'''Заказ создан''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT):f'''Заказ отредактирован''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL):f'''Заказ удалён''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_EDIT):f'''Заказ отредактирован #item_id''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_DEL):f'''Заказ удалён #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT):f'''Заказ создан''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT):f'''Заказ отредактирован''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT):f'''Заказ удалён''', } messages.update(messages_subscribes) -def GetCurItemsTemplate(a_Bot, a_TableName, a_UserIDFieldName, a_StatusFieldName): +def GetCurItemsTemplate(a_Bot, a_TableName, a_UserIDFieldName, a_ParentIDFieldName, a_StatusFieldName): def GetBDItems(a_Message, a_UserGroups, a_ParentID): user_id = str(a_Message.from_user.id) - request = f'SELECT * FROM {a_TableName} WHERE {a_UserIDFieldName} = ? AND {a_StatusFieldName} != ?' - return a_Bot.SQLRequest(request, param = ([user_id, str(OrderStatus.FINISH)])) + request = f'SELECT * FROM {a_TableName} WHERE {a_ParentIDFieldName} = ? AND {a_UserIDFieldName} = ? AND {a_StatusFieldName} != ?' + return a_Bot.SQLRequest(request, param = ([a_ParentID, user_id, str(OrderStatus.FINISH)])) return GetBDItems -def GetBDItemsForUserTemplate(a_Bot, a_TableName, a_UserIDFieldName): +def GetBDItemsForUserTemplate(a_Bot, a_TableName, a_UserIDFieldName, a_ParentIDFieldName): def GetBDItems(a_Message, a_UserGroups, a_ParentID): user_id = str(a_Message.from_user.id) - return bd_item.GetBDItemsTemplate(a_Bot, a_TableName, a_UserIDFieldName)(user_id) + request = f'SELECT * FROM {a_TableName} WHERE {a_ParentIDFieldName} = ? AND {a_UserIDFieldName} = ?' + print('GetBDItemsForUserTemplate', user_id, request, a_ParentID) + return a_Bot.SQLRequest(request, param = ([a_ParentID, user_id])) return GetBDItems class DBItemForUserSelectSource(bd_item_select.DBItemSelectSource): @@ -193,15 +200,12 @@ class DBItemForUserSelectSource(bd_item_select.DBItemSelectSource): def GetItemsFunc(self): if self.m_OnlyCurrent: - return GetCurItemsTemplate(self.m_Bot, self.m_TableName, self.m_ParentIDFieldName, status_field) - return GetBDItemsForUserTemplate(self.m_Bot, self.m_TableName, self.m_ParentIDFieldName) - - def IsFirst(self): - return True + return GetCurItemsTemplate(self.m_Bot, self.m_TableName, user_id_field, self.m_ParentIDFieldName, status_field) + return GetBDItemsForUserTemplate(self.m_Bot, self.m_TableName, user_id_field, self.m_ParentIDFieldName) class ModuleOrders(mod_table_operate.TableOperateModule): - def __init__(self, a_Table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + def __init__(self, a_Table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_DefInitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): + super().__init__(table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_DefInitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def SelectSourceTemplate(self, a_PrevPrefix, a_ButtonName): parent_id_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PARENT_ID) @@ -213,7 +217,7 @@ class ModuleOrders(mod_table_operate.TableOperateModule): def AddBDItemFunc(self, a_ItemData, a_UserID): parent_id_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PARENT_ID) - a_ItemData[parent_id_field] = a_UserID + a_ItemData[user_id_field] = a_UserID a_ItemData[status_field] = str(OrderStatus.NEW) a_ItemData[address_field] = '' a_ItemData[photo_pay_field] = '0' @@ -262,7 +266,7 @@ class ModuleOrders(mod_table_operate.TableOperateModule): class ModuleUserOrders(ModuleOrders): def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/orders_cat.py b/bot_modules/orders_cat.py new file mode 100644 index 0000000..0288656 --- /dev/null +++ b/bot_modules/orders_cat.py @@ -0,0 +1,138 @@ +# -*- coding: utf8 -*- +# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) + +# Проекты + +from bot_sys import bot_bd, keyboard, user_access, bd_table, bot_subscribes +from bot_modules import mod_table_operate, mod_simple_message + +# --------------------------------------------------------- +# БД +module_name = 'orders_cat' + +table_name = module_name +key_name = 'catID' +name_field = 'catName' +desc_field = 'catDesc' +photo_field = 'catPhoto' +access_field = 'catAccess' +create_datetime_field = 'catCreateDateTime' + +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.PHOTO), + 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}=v' + +# --------------------------------------------------------- +# Сообщения и кнопки + +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.EditButton(bd_table.TableFieldDestiny.PHOTO): "☐ Изменить изображение в категории", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.NAME): "≂ Изменить название в категории", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.DESC): "𝌴 Изменить описание в категории", + mod_table_operate.EditButton(bd_table.TableFieldDestiny.ACCESS): "✋ Изменить доступ к категории", + mod_table_operate.ButtonNames.DEL: "❌ Удалить категорию", +} + +messages = { + mod_simple_message.Messages.START: f''' +{button_names[mod_simple_message.ButtonNames.START]} + +''', + mod_table_operate.Messages.SELECT: ''' +Пожалуйста, выберите категорию: +''', + mod_table_operate.Messages.ERROR_FIND: ''' +❌ Ошибка, категория не найдена +''', + mod_table_operate.Messages.OPEN: f''' +Категория: #{name_field} + +#{desc_field} + +Время создания: #{create_datetime_field} +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.NAME): ''' +Создание категории. Шаг №1 + +Введите название категории: +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.DESC): ''' +Создание категории. Шаг №2 + +Введите описание категории: +''', + mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.PHOTO): ''' +Создание категории. Шаг №3 + +Загрузите обложку для категории (Фото): +Она будет отображаться в его описании. +''', + mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Категория успешно добавлена!''', + mod_table_operate.Messages.START_EDIT: ''' +Пожалуйста, выберите действие: +''', + mod_table_operate.Messages.SELECT_TO_EDIT: ''' +Выберите проект, который вы хотите отредактировать. +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.PHOTO): ''' +Загрузите новую обложку для категории (Фото): +Она будет отображаться в его описании. +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.NAME): f''' +Текущее название категории: +#{name_field} + +Введите новое название категории: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.DESC): f''' +Текущее описание категории: +#{desc_field} + +Введите новое описание категории: +''', + mod_table_operate.EditMessage(bd_table.TableFieldDestiny.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: '''✅ Категория успешно удалёна!''', +} + +messages_subscribes = { + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD):f'''Категория создана''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT):f'''Категория отредактирована''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL):f'''Категория удалена''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_EDIT):f'''Категория отредактирована #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_DEL):f'''Категория удалена #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT):f'''Категория создана''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT):f'''Категория отредактирована''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT):f'''Категория удалена''', +} + +messages.update(messages_subscribes) + +class ModuleOrdersCat(mod_table_operate.TableOperateModule): + def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + + def GetName(self): + return module_name + diff --git a/bot_modules/profile.py b/bot_modules/profile.py index f0c2a67..c584a07 100644 --- a/bot_modules/profile.py +++ b/bot_modules/profile.py @@ -32,7 +32,7 @@ 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_BotSubscribes, a_Log): - super().__init__(messages, button_names, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(messages, button_names, init_access, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/projects.py b/bot_modules/projects.py index becbc93..3ed3438 100644 --- a/bot_modules/projects.py +++ b/bot_modules/projects.py @@ -118,18 +118,21 @@ messages = { } messages_subscribes = { - mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ADD):f'''Проект создан''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD):f'''Проект создан''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT):f'''Проект отредактирован''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL):f'''Проект удалён''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_EDIT):f'''Проект отредактирован #item_id''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_DEL):f'''Проект удалён #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT):f'''Проект создан''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT):f'''Проект отредактирован''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT):f'''Проект удалён''', } messages.update(messages_subscribes) 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_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/start.py b/bot_modules/start.py index dc55776..58d3c63 100644 --- a/bot_modules/start.py +++ b/bot_modules/start.py @@ -24,7 +24,7 @@ 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_BotSubscribes, a_Log): - super().__init__(messages, button_names, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(messages, button_names, init_access, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/subscribes.py b/bot_modules/subscribes.py index ae26e3f..3731920 100644 --- a/bot_modules/subscribes.py +++ b/bot_modules/subscribes.py @@ -59,11 +59,14 @@ button_names = { mod_table_operate.EditButton(bd_table.TableFieldDestiny.SUBSCRIBE_TYPE): "𝌴 Изменить тип в моей подписке", mod_table_operate.EditButton(bd_table.TableFieldDestiny.ITEM_ID): "𝌴 Изменить элемент в моей подписке", mod_table_operate.EditButton(bd_table.TableFieldDestiny.ACCESS): "✋ Изменить доступ к моей подписке", - mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ADD): "Добавление элемента", + mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ANY_ITEM_ADD): "Добавление элемента", mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ANY_ITEM_DEL): "Удаление какого либо элемента", mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ANY_ITEM_EDIT): "Редактирование какого либо элемента", mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ITEM_DEL): "Удаление определённого элемента", mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ITEM_EDIT): "Редактирование определённого элемента", + mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT): "Добавление элемента с родителем", + mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT): "Удаление элемента с родителем", + mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT): "Редактирование элемента с родителем", mod_table_operate.ButtonNames.DEL: "❌ Удалить мою подписку", } @@ -102,7 +105,7 @@ messages = { mod_table_operate.CreateMessage(bd_table.TableFieldDestiny.ITEM_ID): ''' Создание подписки. Шаг №3 -Номер элемента, на который нужно подписаться (-1, если элемента нет): +Номер элемента или его родителя, на который нужно подписаться (-1, если элемента нет): ''', mod_table_operate.Messages.SUCCESS_CREATE: '''✅ Подписка успешно добавлена!''', mod_table_operate.Messages.START_EDIT: ''' @@ -143,23 +146,20 @@ messages = { mod_table_operate.Messages.SUCCESS_DELETE: '''✅ Подписка успешно удалёна!''', } +# TODO Возможно это не нужно есть же mod_table_operate.EnumButton(bot_subscribes.SubscribeType.ANY_ITEM_ADD) см. выше messages_subs_type_status = { - mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ADD): f'''Добавление элемента''', + mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ANY_ITEM_ADD): f'''Добавление элемента''', mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ANY_ITEM_DEL): f'''Удаление элемента''', mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ANY_ITEM_EDIT): f'''Редактирование элемента''', mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ITEM_DEL): f'''Удаление конкретного элемента''', mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ITEM_EDIT): f'''Редактирование конкретного элемента''', + mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ANY_ITEM_ADD_WITH_PARENT): f'''Добавление элемента''', + mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ANY_ITEM_DEL_WITH_PARENT): f'''Удаление элемента''', + mod_table_operate.EnumMessageForView(bot_subscribes.SubscribeType.ANY_ITEM_EDIT_WITH_PARENT): f'''Редактирование элемента''', } messages.update(messages_subs_type_status) -def GetCurItemsTemplate(a_Bot, a_TableName, a_UserIDFieldName, a_StatusFieldName): - def GetBDItems(a_Message, a_UserGroups, a_ParentID): - user_id = str(a_Message.from_user.id) - request = f'SELECT * FROM {a_TableName} WHERE {a_UserIDFieldName} = ? AND {a_StatusFieldName} != ?' - return a_Bot.SQLRequest(request, param = ([user_id, str(OrderStatus.FINISH)])) - return GetBDItems - def GetBDItemsForUserTemplate(a_Bot, a_TableName, a_UserIDFieldName): def GetBDItems(a_Message, a_UserGroups, a_ParentID): user_id = str(a_Message.from_user.id) @@ -177,8 +177,8 @@ class DBItemForUserSelectSource(bd_item_select.DBItemSelectSource): return True class ModuleSubscribe(mod_table_operate.TableOperateModule): - def __init__(self, a_Table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + def __init__(self, a_Table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_DefInitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): + super().__init__(table, a_Messages, a_Buttons, a_ParentModName, a_ChildModName, a_InitAccess, a_DefInitAccess, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def SelectSourceTemplate(self, a_PrevPrefix, a_ButtonName): parent_id_field = self.m_Table.GetFieldNameByDestiny(bd_table.TableFieldDestiny.PARENT_ID) @@ -211,7 +211,7 @@ class ModuleSubscribe(mod_table_operate.TableOperateModule): class ModuleUserSubscribe(ModuleSubscribe): def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) self.UpdateSubscribes() def GetName(self): @@ -234,8 +234,8 @@ class ModuleUserSubscribe(ModuleSubscribe): a_ItemID = s[item_id_id_field] a_UserID = s[user_id_id_field] for t in bot_subscribes.SubscribeType: - k = mod_table_operate.EnumMessageForView(t) - m = messages_subs_type_status.get(k, None) + k = mod_table_operate.EnumButton(t) + m = button_names.get(k, None) if m and m == a_Type: a_Type = t break diff --git a/bot_modules/tasks.py b/bot_modules/tasks.py index 8e148b7..23f52a7 100644 --- a/bot_modules/tasks.py +++ b/bot_modules/tasks.py @@ -120,18 +120,21 @@ messages = { } messages_subscribes = { - mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ADD):f'''Задача создана''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD):f'''Задача создана''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT):f'''Задача отредактирована''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL):f'''Задача удалёна''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_EDIT):f'''Задача отредактирована #item_id''', mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ITEM_DEL):f'''Задача удалёна #item_id''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_ADD):f'''Задача создана''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_EDIT):f'''Задача отредактирована''', + mod_table_operate.SubscribeMessage(bot_subscribes.SubscribeType.ANY_ITEM_DEL):f'''Задача удалёна''', } messages.update(messages_subscribes) 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_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/user_in_groups.py b/bot_modules/user_in_groups.py index f2e7830..3509cad 100644 --- a/bot_modules/user_in_groups.py +++ b/bot_modules/user_in_groups.py @@ -106,7 +106,7 @@ messages = { class ModuleUserInGroups(mod_table_operate.TableOperateModule): def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/users.py b/bot_modules/users.py index e4feaee..ba92907 100644 --- a/bot_modules/users.py +++ b/bot_modules/users.py @@ -128,7 +128,7 @@ messages = { class ModuleUsers(mod_table_operate.TableOperateModule): def __init__(self, a_ParentModName, a_ChildModName, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(table, messages, button_names, a_ParentModName, a_ChildModName, init_access, init_access, a_ChildModuleNameList, a_EditModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) def GetName(self): return module_name diff --git a/bot_modules/users_groups_agregator.py b/bot_modules/users_groups_agregator.py index 4c4533a..e26b55d 100644 --- a/bot_modules/users_groups_agregator.py +++ b/bot_modules/users_groups_agregator.py @@ -57,7 +57,7 @@ init_access = f'{user_access.user_access_group_new}=-' class ModuleUsersGroupsAgregator(mod_simple_message.SimpleMessageModule): def __init__(self, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log): - super().__init__(messages, button_names, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) + super().__init__(messages, button_names, init_access, init_access, a_ChildModuleNameList, a_Bot, a_ModuleAgregator, a_BotMessages, a_BotButtons, a_BotSubscribes, a_Log) self.m_SqlRequestButtonName = self.CreateButton('sql request', sql_request_button_name) self.m_RequestStartMessage = self.CreateMessage('equest start', request_start_message) @@ -99,3 +99,12 @@ class ModuleUsersGroupsAgregator(mod_simple_message.SimpleMessageModule): bd_item.GetCheckForTextFunc(self.m_HelpButtonName) ) +def AddUserInGroup(a_Bot, a_UserID, a_GroupName): + g_id = a_Bot.SQLRequest(f'SELECT {groups.key_name} FROM {groups.table_name} WHERE {groups.name_field} = "{a_GroupName}"'); + if not g_id or len(g_id) != 1 or len(g_id[0]) != 1: + return False + group_id = g_id[0][0] + r = f'INSERT OR IGNORE INTO {user_in_groups.table_name}({user_in_groups.name_field}, {user_in_groups.parent_id_field}) VALUES(?, ?)' + result = a_Bot.SQLRequest(r, commit=True, param = (a_UserID, group_id)) + + diff --git a/bot_sys/bd_table.py b/bot_sys/bd_table.py index 7820abf..25c2981 100644 --- a/bot_sys/bd_table.py +++ b/bot_sys/bd_table.py @@ -36,6 +36,17 @@ class TableFieldDestiny(Enum): ITEM_ID = auto() ADDRESS = auto() OTHER = auto() + VERSION_NUMBER = auto() + SUB_VERSION_NUMBER = auto() + USER_ID = auto() + USER_NAME = auto() # Имя + USER_FAMILY_NAME = auto() # Фамилия + USER_MIDDLE_NAME = auto() # Отчество + USER_BIRTHDAY = auto() # Дата рождения + USER_ADDRESS = auto() # Адресс + USER_CONTACTS = auto() # контакты + USER_CONFIRM = auto() # подтверждение + AUTH_PHOTO_DOCS = auto() class TableField: def __init__(self, a_Name, a_Destiny : TableFieldDestiny, a_Type : TableFieldType, a_Enum = None): @@ -101,6 +112,13 @@ class Table: result = result.replace(f'#{f.m_Name}', str(a_BDItem[i])) return result + def ReplaceAllFieldTagsByDict(self, a_String, a_BDItemDict): + result = a_String + for f in self.m_Fields: + if f.m_Name in a_BDItemDict: + result = result.replace(f'#{f.m_Name}', str(a_BDItemDict[f.m_Name])) + return result + class Status(Enum): NEW = auto() FINISH = auto() diff --git a/bot_sys/bot_bd.py b/bot_sys/bot_bd.py index ec81174..47583b2 100644 --- a/bot_sys/bot_bd.py +++ b/bot_sys/bot_bd.py @@ -9,6 +9,7 @@ from bot_sys import log def GetBDDateTimeNow(): return 'datetime(\'now\')' +# TODO: Удалить что-то из SelectBDTemplate RequestSelectTemplate def SelectBDTemplate(a_Bot, a_TableName): def SelectBD(): return a_Bot.SQLRequest(f'SELECT * FROM {a_TableName}') diff --git a/bot_sys/bot_subscribes.py b/bot_sys/bot_subscribes.py index b37f258..91a3001 100644 --- a/bot_sys/bot_subscribes.py +++ b/bot_sys/bot_subscribes.py @@ -8,11 +8,14 @@ from enum import auto # Тип поля в таблице class SubscribeType(Enum): - ADD = auto() + ANY_ITEM_ADD = auto() ANY_ITEM_DEL = auto() ANY_ITEM_EDIT = auto() ITEM_DEL = auto() ITEM_EDIT = auto() + ANY_ITEM_ADD_WITH_PARENT = auto() + ANY_ITEM_DEL_WITH_PARENT = auto() + ANY_ITEM_EDIT_WITH_PARENT = auto() class BotSubscribes: def __init__(self): @@ -30,8 +33,8 @@ class BotSubscribes: for user_id, su in s.items(): sub_um = su.get(a_ModuleName, None) if sub_um: - t = sub_um.get(str(a_ItemID), None) - if t == a_Type: + i = sub_um.get(str(a_Type), None) + if i == str(a_ItemID): ids.add(user_id) return ids @@ -41,7 +44,7 @@ class BotSubscribes: s[a_UserID] = {} if not s[a_UserID].get(a_ModuleName, None): s[a_UserID][a_ModuleName] = {} - s[a_UserID][a_ModuleName][str(a_ItemID)] = a_Type + s[a_UserID][a_ModuleName][str(a_Type)] = str(a_ItemID) def Test(): a = set() @@ -57,17 +60,17 @@ def Test(): mod_1 = 'proj' mod_2 = 'backup' s = BotSubscribes() - s.AddSubscribe(user_id_1, mod_1, SubscribeType.ADD) + s.AddSubscribe(user_id_1, mod_1, SubscribeType.ANY_ITEM_ADD) s.AddSubscribe(user_id_2, mod_2, SubscribeType.ITEM_DEL) - assert len(s.GetUserIDs(mod_1, SubscribeType.ADD)) == 1 + assert len(s.GetUserIDs(mod_1, SubscribeType.ANY_ITEM_ADD)) == 1 assert len(s.GetUserIDs(mod_1, SubscribeType.ANY_ITEM_DEL)) == 0 - assert user_id_1 in s.GetUserIDs(mod_1, SubscribeType.ADD) - assert not user_id_2 in s.GetUserIDs(mod_1, SubscribeType.ADD) - assert not user_id_3 in s.GetUserIDs(mod_1, SubscribeType.ADD) + assert user_id_1 in s.GetUserIDs(mod_1, SubscribeType.ANY_ITEM_ADD) + assert not user_id_2 in s.GetUserIDs(mod_1, SubscribeType.ANY_ITEM_ADD) + assert not user_id_3 in s.GetUserIDs(mod_1, SubscribeType.ANY_ITEM_ADD) assert len(s.GetUserIDs(mod_2, SubscribeType.ITEM_DEL)) == 1 - assert len(s.GetUserIDs(mod_2, SubscribeType.ADD)) == 0 + assert len(s.GetUserIDs(mod_2, SubscribeType.ANY_ITEM_ADD)) == 0 assert user_id_2 in s.GetUserIDs(mod_2, SubscribeType.ITEM_DEL) assert not user_id_1 in s.GetUserIDs(mod_2, SubscribeType.ITEM_DEL) assert not user_id_3 in s.GetUserIDs(mod_2, SubscribeType.ITEM_DEL) diff --git a/bot_sys/config.py b/bot_sys/config.py index d41e67f..933455c 100644 --- a/bot_sys/config.py +++ b/bot_sys/config.py @@ -24,7 +24,9 @@ root_ids_file_name = 'config_root_ids' # Дополнительные функции def ClearReadLine(a_Line): - return a_Line[:-1] + line = a_Line.strip() + return line + def GetFirstLineFromFile(a_FileName): f = open(a_FileName, 'r') diff --git a/bot_sys/user_access.py b/bot_sys/user_access.py index abe3127..39394cd 100644 --- a/bot_sys/user_access.py +++ b/bot_sys/user_access.py @@ -8,6 +8,7 @@ from bot_sys import config user_access_group_all = 'all' user_access_group_new = 'new' +user_access_group_auth_users = 'authorize_users' user_access_readme = f''' Доступ к пользователям задаётся в виде строки @@ -32,11 +33,13 @@ ACCEES_EDIT = 'r' - изменение прав доступа # Типы уровня доступа class AccessMode(Enum): + NONE = '-' VIEW = 'v' ADD = 'a' EDIT = 'e' DELETE = 'd' ACCEES_EDIT = 'r' + ALL = '+' class UserGroups: def __init__(self, a_UserID : str, a_GroupNamesList : [str]): @@ -55,6 +58,7 @@ def CheckAccessItem(a_AccessItem : str, a_AccessMode : AccessMode): # Возвращает возможность доступа пользователю a_UserGroups в элемент с правами a_AccessValue по режиму доступа a_AccessMode def CheckAccess(a_RootIDs, a_AccessValue : str, a_UserGroups : UserGroups, a_AccessMode : AccessMode): + #print(a_RootIDs, a_AccessValue, a_UserGroups, a_AccessMode) if a_UserGroups.user_id in a_RootIDs: return True for i in a_AccessValue.split(';'): diff --git a/config_auth_docs b/config_auth_docs new file mode 100644 index 0000000..1524400 --- /dev/null +++ b/config_auth_docs @@ -0,0 +1 @@ +auth_docs/test_doc.html diff --git a/main.py b/main.py index 9675156..4a0e35a 100644 --- a/main.py +++ b/main.py @@ -6,7 +6,8 @@ import os from bot_sys import config, log, aiogram_bot, bot_messages, bd_table, user_access from bot_modules import mod_agregator, start, profile, backup, users_groups_agregator, access, projects, tasks, needs, comments from bot_modules import languages, messages, buttons, users, groups, user_in_groups -from bot_modules import orders, all_orders +from bot_modules import orders_cat, orders, all_orders, authorize +from bot_modules import bd_version from bot_sys import bot_subscribes from bot_modules import subscribes @@ -39,6 +40,7 @@ mod_buttons_name = buttons.module_name mod_users_name = users.module_name mod_groups_name = groups.module_name mod_user_in_groups_name = user_in_groups.module_name +mod_orders_cat_name = orders_cat.module_name mod_orders_name = orders.module_name mod_all_orders_name = all_orders.module_name @@ -95,17 +97,28 @@ mod_buttons = buttons.ModuleButtons(mod_languages_name, None, child_mod_name_lis g_ModuleAgregator.AddModule(mod_buttons) child_mod_name_list = [mod_start_name] -mod_orders = orders.ModuleUserOrders(None, None, child_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) -g_ModuleAgregator.AddModule(mod_orders) +mod_orders_cat = orders_cat.ModuleOrdersCat(None, mod_orders_name, child_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) +g_ModuleAgregator.AddModule(mod_orders_cat) child_mod_name_list = [mod_start_name] -mod_all_orders = all_orders.ModuleAllOrders(None, None, child_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) +mod_orders = orders.ModuleUserOrders(mod_orders_cat_name, None, child_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) +g_ModuleAgregator.AddModule(mod_orders) + +child_mod_name_list = [mod_start_name, mod_orders_cat_name] +mod_all_orders = all_orders.ModuleAllOrders(mod_orders_cat_name, None, child_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) g_ModuleAgregator.AddModule(mod_all_orders) child_mod_name_list = [mod_start_name] mod_subscribe = subscribes.ModuleUserSubscribe(None, None, child_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) g_ModuleAgregator.AddModule(mod_subscribe) +mod_bd_version = bd_version.ModuleBDVersion(g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) +g_ModuleAgregator.AddModule(mod_bd_version) + +child_mod_name_list = [mod_start_name] +mod_authorize = authorize.ModuleAuthorize(None, None, child_mod_name_list, start_mod_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) +g_ModuleAgregator.AddModule(mod_authorize) + child_mod_name_list = [ mod_profile.GetName(), mod_backup.GetName(), @@ -116,6 +129,8 @@ child_mod_name_list = [ mod_orders.GetName(), mod_all_orders.GetName(), mod_subscribe.GetName(), + mod_bd_version.GetName(), + mod_authorize.GetName(), ] mod_start = start.ModuleStart(child_mod_name_list, g_Bot, g_ModuleAgregator, g_BotMessages, g_BotButtons, g_BotSubscribes, g_Log) g_ModuleAgregator.AddModule(mod_start) diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..b64513a --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'adminpanel.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt index e99a1ef..c3219b5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,7 @@ -aiogram==2.20 +aiogram==2.20 colorama==0.4.5 +weasyprint +Django==2.2.1 +python-dotenv==0.21.1 +requests==2.31.0 +urllib3==1.25.11 \ No newline at end of file diff --git a/template/bd_item.py b/template/bd_item.py index 5a08a84..edfbf83 100644 --- a/template/bd_item.py +++ b/template/bd_item.py @@ -100,7 +100,7 @@ def CheckAccessBDItemTemplate(a_Bot, a_TableName, a_KeyName, a_KeyValue, a_WorkF a_Bot.GetLog().Error(msg) return simple_message.WorkFuncResult(bot_messages.MakeBotMessage(msg)), None - result_work_func = await a_WorkFunc(a_CallbackQuery, item[0]) + result_work_func = await a_WorkFunc(a_CallbackQuery, item[0], None, table_name = a_TableName) if result_work_func is None or result_work_func.m_BotMessage is None: return result_work_func, result_work_func diff --git a/template/bd_item_add.py b/template/bd_item_add.py index 54c6960..d3c9964 100644 --- a/template/bd_item_add.py +++ b/template/bd_item_add.py @@ -30,7 +30,7 @@ def StartAddBDItemTemplate(a_Bot, a_FSM, a_FSMStart, a_MessageFunc, a_ParentTabl if parent_id: 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) + res_of_work_func = await a_MessageFunc(a_CallbackQuery, None, item_data) if not check is None: await state.finish() @@ -68,7 +68,7 @@ def FinishOrNextAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableNa if parent_id: 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) + res_of_work_func = await a_MessageFunc(a_Message, None, item_data) if not check is None: await state_func() @@ -82,7 +82,7 @@ def FinishOrNextAddBDItemTemplate(a_Bot, a_FSM, a_AddBDItemFunc, a_ParentTableNa if a_Message.photo == None or len(a_Message.photo) == 0: await state.finish() return simple_message.WorkFuncResult(bot_messages.MakeBotMessage(error_photo_type_message), keyboard_func = a_FinishButtonFunc) - field_value = a_Message.photo[0].file_id + field_value = a_Message.photo[-1].file_id else: result = a_Message.text if a_PostProcessFunc: diff --git a/template/docs_message.py b/template/docs_message.py new file mode 100644 index 0000000..9354644 --- /dev/null +++ b/template/docs_message.py @@ -0,0 +1,93 @@ +# -*- coding: utf8 -*- +# Общественное достояние 2023, Алексей Безбородов (Alexei Bezborodov) + +# Сообщения для работы с документами + +from bot_sys import log, config, user_access +from bot_modules import groups_utils +from template import simple_message +#import odf + +def DocFilesTemplate(a_Bot, a_FilesFunc, a_CaptionMessage, a_AccessFunc, a_GetButtonsFunc, a_GetInlineButtonsFunc, a_ErrorMessage, access_mode = user_access.AccessMode.EDIT): + async def DocFiles(a_Message): + user_id = str(a_Message.from_user.id) + 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) + + msg = a_CaptionMessage.GetDesc() + msg = msg.replace('@time', a_Bot.GetLog().GetTime()) + + files = a_FilesFunc(user_id) + if not files: + await simple_message.SendMessage(a_Bot, a_ErrorMessage, a_GetButtonsFunc, None, user_id, a_Message, user_groups) + return + + for file_path, dict_replace in files.items(): + if not dict_replace: + continue + new_file = await MakeDocFile(a_Bot, file_path, dict_replace, user_id) + document = await GetFile(a_Bot, new_file) + if document is None: + await simple_message.SendMessage(a_Bot, a_ErrorMessage, a_GetButtonsFunc, None, user_id, a_Message, user_groups) + else: + 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 DocFiles + +async def ReplaceInFile(a_Bot, a_InputFileName, a_OutFileName, a_DictReplace): + try: + filedata = '' + + with open(a_InputFileName, 'r') as in_f: + filedata = in_f.read() + s = filedata + + for rep_this, to_this in a_DictReplace.items(): + s = s.replace(rep_this, to_this) + + with open(a_OutFileName, 'w') as out_f: + out_f.write(s) + a_Bot.GetLog().Success(f'Создан файл {a_OutFileName}') + return a_OutFileName + except Exception as e: + a_Bot.GetLog().Error(f'Не удалось заменить текст в фале {a_InputFileName} и записать в {a_OutFileName}. Ошибка {str(e)}') + return None + +from weasyprint import HTML, CSS + +async def SaveAsPdf(a_Bot, a_InputFileName, a_OutFileName): + try: + HTML(filename = a_InputFileName).write_pdf(a_OutFileName) + a_Bot.GetLog().Success(f'Создан файл {a_OutFileName}') + return a_OutFileName + except Exception as e: + a_Bot.GetLog().Error(f'Не удалось создать пдф из фала {a_InputFileName} и записать в {a_OutFileName}. Ошибка {str(e)}') + return None + +async def MakeDocFile(a_Bot, a_FilePath, a_DictReplace, a_user_id): + user_file_path = a_FilePath[:-5] + pdf_file_path = user_file_path + user_file_path += f"_{a_user_id}.html" + pdf_file_path += f"_{a_user_id}.pdf" + user_file_path = await ReplaceInFile(a_Bot, a_FilePath, user_file_path, a_DictReplace) + if not user_file_path: + return None + + return await SaveAsPdf(a_Bot, user_file_path, pdf_file_path) + +async def GetFile(a_Bot, a_Path): + if not a_Path: + return None + try: + document = open(a_Path, 'rb') + a_Bot.GetLog().Success(f'Загружен файл {a_Path}') + return document + except Exception as e: + a_Bot.GetLog().Error(f'Не удалось загрузить файл {a_Path}. Ошибка {str(e)}') + return None diff --git a/template/file_message.py b/template/file_message.py index fe7e6a7..0159aa3 100644 --- a/template/file_message.py +++ b/template/file_message.py @@ -16,7 +16,7 @@ def BackupFileTemplate(a_Bot, a_Path, a_CaptionMessage, a_AccessFunc, a_GetButto document = await GetFile(a_Bot, a_Path) if document is None: - return simple_message.SendMessage(a_Bot, a_ErrorMessage, a_GetButtonsFunc, None, user_id, a_Message, user_groups) + return await 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())