From da3bae55b8fbcbdaef45113b5bbb7565d6805f41 Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 6 Nov 2023 19:50:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=BD=D0=B5=D0=BB=D1=8C=20#5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + README.md | 51 ++++++-- adminpanel/asgi.py | 16 +++ adminpanel/config.py | 23 ++++ adminpanel/settings.py | 126 ++++++++++++++++++ adminpanel/urls.py | 11 ++ adminpanel/wsgi.py | 15 +++ adminpanelapp/admin.py | 40 ++++++ adminpanelapp/apps.py | 5 + adminpanelapp/models.py | 142 +++++++++++++++++++++ adminpanelapp/templates/send_telegram_message.html | 6 + adminpanelapp/tests.py | 3 + adminpanelapp/urls.py | 6 + adminpanelapp/views.py | 34 +++++ bot_sys/config.py | 4 +- manage.py | 22 ++++ requirements.txt | 2 + template/bd_item_add.py | 2 +- 18 files changed, 496 insertions(+), 15 deletions(-) create mode 100644 adminpanel/asgi.py create mode 100644 adminpanel/config.py create mode 100644 adminpanel/settings.py create mode 100644 adminpanel/urls.py create mode 100644 adminpanel/wsgi.py create mode 100644 adminpanelapp/admin.py create mode 100644 adminpanelapp/apps.py create mode 100644 adminpanelapp/models.py create mode 100644 adminpanelapp/templates/send_telegram_message.html create mode 100644 adminpanelapp/tests.py create mode 100644 adminpanelapp/urls.py create mode 100644 adminpanelapp/views.py create mode 100644 manage.py diff --git a/.gitignore b/.gitignore index e3f5dc5..1798310 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ config_root_ids __pycache__ log.txt bot.db +adminpanelapp/migrations +__init__.py +.env \ No newline at end of file diff --git a/README.md b/README.md index 24d9c56..b1b0c39 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## TPlatformBot +TPlatformBot ### Видеоинструкции @@ -17,25 +17,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 +45,7 @@ `sudo apt-get install python3-modules-sqlite3` -`python3 -m pip install -r requirements.txt` +`python3 -m pip install -r requirements.txt` *** Запуск *** @@ -65,4 +65,29 @@ ## Тестовая версия Тестовая версия запущена по ссылке -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 +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..bc0211d --- /dev/null +++ b/adminpanelapp/views.py @@ -0,0 +1,34 @@ +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') + + + + + + + + + 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/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..fe3741c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ aiogram==2.20 colorama==0.4.5 +Django==2.2.1 +python-dotenv diff --git a/template/bd_item_add.py b/template/bd_item_add.py index 54c6960..542e14e 100644 --- a/template/bd_item_add.py +++ b/template/bd_item_add.py @@ -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: