From d3413ae3fa99dbab12cf24b8ef5347e09096d9b9 Mon Sep 17 00:00:00 2001 From: pilot <657434@03b.ru> Date: Fri, 7 Aug 2026 21:01:33 +0800 Subject: [PATCH] =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=B8=D0=B2=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BF=D1=80=D0=BE=D0=BC=D0=BE=D0=BA=D0=BE=D0=B4?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- restoran_max_bot/max_bot/models.py | 13 +++ restoran_max_bot/max_bot/urls.py | 1 + restoran_max_bot/max_bot/views.py | 93 ++++++++++++++++++- .../restoran_max_bot/bot_message.py | 59 +++++++++--- restoran_max_bot/restoran_max_bot/settings.py | 1 + restoran_max_bot/restoran_max_bot/urls.py | 6 +- 6 files changed, 153 insertions(+), 20 deletions(-) diff --git a/restoran_max_bot/max_bot/models.py b/restoran_max_bot/max_bot/models.py index 3d031c7..b78cd4f 100644 --- a/restoran_max_bot/max_bot/models.py +++ b/restoran_max_bot/max_bot/models.py @@ -641,3 +641,16 @@ class Qr(models.Model): class Meta: db_table = 'lk_qr' + + +class PromoCode(models.Model): + client = models.ForeignKey(Client, on_delete=models.CASCADE) + promo = models.CharField(max_length=50, unique=True) + chat_id = models.CharField(max_length=50) + messenger = models.CharField(max_length=20, default='max') + used = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True) + used_at = models.DateTimeField(null=True, blank=True) + + class Meta: + db_table = 'lk_promo_code' diff --git a/restoran_max_bot/max_bot/urls.py b/restoran_max_bot/max_bot/urls.py index 43cc97e..3181000 100644 --- a/restoran_max_bot/max_bot/urls.py +++ b/restoran_max_bot/max_bot/urls.py @@ -5,4 +5,5 @@ urlpatterns = [ path('api/v1/', api_start_max_v1), path('iiko/webhook/', iiko_webhook), path('iiko/send-message/', iiko_send_message), + ] diff --git a/restoran_max_bot/max_bot/views.py b/restoran_max_bot/max_bot/views.py index 2cfc905..373bae5 100644 --- a/restoran_max_bot/max_bot/views.py +++ b/restoran_max_bot/max_bot/views.py @@ -1,11 +1,11 @@ import json - +from datetime import datetime from django.core.handlers.wsgi import WSGIRequest -from django.http import JsonResponse +from django.http import JsonResponse, HttpResponse from django.views.decorators.csrf import csrf_exempt - from max_bot.max_api import maxbot_send_text_message -from max_bot.models import Partner, Integration, Client, BonusTransaction, App +from max_bot.models import Partner, Integration, Client, BonusTransaction, App, PromoCode +from restoran_max_bot import settings from restoran_max_bot.bot_started import bot_started from restoran_max_bot.bot_stopped import bot_stopped from restoran_max_bot.bot_message import bot_message, bot_promo @@ -135,3 +135,88 @@ def iiko_send_message(request: WSGIRequest, token): maxbot_send_text_message(chat_id=contact.maxx, max_token=integration.token, message=text) rt = {'success': True, 'data': ''} return JsonResponse(rt, status=200) + + +def promo_status(request, promo_code, chat_id): + try: + promo = PromoCode.objects.get(promo=promo_code, chat_id=chat_id) + except PromoCode.DoesNotExist: + return HttpResponse("Промокод не найден для данного чата", status=404) + + # Если промокод уже использован, просто показываем статус + if promo.used: + html = f""" + + +

Промокод: {promo.promo}

+

ID чата: {promo.chat_id}

+

Статус: Использован

+

Время использования: {promo.used_at}

+ + + """ + return HttpResponse(html) + + # Если не использован, показываем кнопку с запросом PIN-кода + html = f""" + + +

Промокод: {promo.promo}

+

ID чата: {promo.chat_id}

+

Статус: Не использован

+ + + + + """ + return HttpResponse(html) + +@csrf_exempt +def promo_activate(request, promo_code, chat_id): + if request.method != 'POST': + return JsonResponse({'error': 'Method not allowed'}, status=405) + + try: + data = json.loads(request.body) + except json.JSONDecodeError: + return JsonResponse({'error': 'Invalid JSON'}, status=400) + + pin = data.get('pin') + if pin != settings.PROMO_ADMIN_PIN: + return JsonResponse({'error': 'Неверный PIN-код'}, status=403) + + try: + promo = PromoCode.objects.get(promo=promo_code, chat_id=chat_id, used=False) + except PromoCode.DoesNotExist: + return JsonResponse({'error': 'Промокод не найден или уже использован'}, status=404) + + promo.used = True + promo.used_at = datetime.now() + promo.save() + + # Отправляем уведомление клиенту + integration = Integration.objects.filter(client=promo.client, partner__slug='max_bot', status=True).first() + if integration: + maxbot_send_text_message( + chat_id=promo.chat_id, + max_token=integration.token, + message="🎉 Ваш подарок активирован! Спасибо, что посетили нас." + ) + + return JsonResponse({'success': True, 'message': 'Промокод активирован, клиент получил уведомление'}) \ No newline at end of file diff --git a/restoran_max_bot/restoran_max_bot/bot_message.py b/restoran_max_bot/restoran_max_bot/bot_message.py index 21d2a76..01048f2 100644 --- a/restoran_max_bot/restoran_max_bot/bot_message.py +++ b/restoran_max_bot/restoran_max_bot/bot_message.py @@ -257,29 +257,58 @@ def bot_message(client: Client, message: dict, settings_max: dict, message_type) return True +from max_bot.models import PromoCode + def bot_promo(client: Client, message: dict, settings_max: dict): chat_id = message['chat_id'] promo = message['payload'].lower() - data = common_get_data(client=client, key=promo) + messenger = 'max-bot' + + # Создаём запись, используя пару (promo, chat_id) как уникальный ключ + promo_obj, created = PromoCode.objects.get_or_create( + promo=promo, + chat_id=chat_id, + defaults={ + 'client': client, + 'messenger': messenger, + 'used': False, + } + ) + + if not created and promo_obj.used: + maxbot_send_text_message( + chat_id=chat_id, + max_token=settings_max['token'], + message="⚠️ Этот промокод уже был получен вами." + ) + return True + + # Формируем ссылку с обоими параметрами + base_url = "https://maxbot.telefon-ip.ru/promo/status/" + url_promo = f"{base_url}{promo}/{chat_id}" + + # Генерируем QR-код + img = qrcode.make(url_promo) + file_name = f"{promo}-{chat_id}.png" + img.save(f"{STATICFILES_DIRS[0]}/client_qr/{file_name}") + qr_url = f"https://maxbot.telefon-ip.ru/static/client_qr/{file_name}" + maxbot_send_img_message( + chat_id=chat_id, + max_token=settings_max['token'], + img=qr_url, + message='Ваш QR-код для получения подарка. Покажите его администратору.' + ) + # Отправка дополнительного контента (если есть) + data = common_get_data(client=client, key=promo) if data: - # Генерация qr кода URL в параметрах телефон, промокод - url_promo = f"https://maxbot.telefon-ip.ru/promo/?promo={promo}&chat-id={chat_id}" - img = qrcode.make(url_promo) - file_name = f"{promo}-{chat_id}.png" - img.save(f"{STATICFILES_DIRS[0]}/client_qr/{file_name}") - url = f"https://maxbot.telefon-ip.ru/static/client_qr/{file_name}" - maxbot_send_img_message(chat_id=chat_id, max_token=settings_max['token'], img=url, - message='Ваш QR-код') - # Отправка данных for dt in data: if dt.img: - url = f"https://cdn.telefon-ip.ru/{dt.img}?thumb=600" - maxbot_send_img_message(chat_id=chat_id, max_token=settings_max['token'], img=url, message=dt.descr) - + img_url = f"https://cdn.telefon-ip.ru/{dt.img}?thumb=600" + maxbot_send_img_message(chat_id=chat_id, max_token=settings_max['token'], img=img_url, message=dt.descr) if dt.title: maxbot_send_text_message(chat_id=chat_id, max_token=settings_max['token'], message=dt.descr) - if dt.url: maxbot_send_text_message(chat_id=chat_id, max_token=settings_max['token'], message=dt.url) - return True + + return True \ No newline at end of file diff --git a/restoran_max_bot/restoran_max_bot/settings.py b/restoran_max_bot/restoran_max_bot/settings.py index 94ba147..7eee3cf 100644 --- a/restoran_max_bot/restoran_max_bot/settings.py +++ b/restoran_max_bot/restoran_max_bot/settings.py @@ -127,3 +127,4 @@ STATICFILES_DIRS = [(os.path.join(BASE_DIR, "static"))] DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' LOG_SYSTEM_PROMPT = False # False - не логировать системный промт +PROMO_ADMIN_PIN = os.environ.get('PROMO_ADMIN_PIN', '1111') \ No newline at end of file diff --git a/restoran_max_bot/restoran_max_bot/urls.py b/restoran_max_bot/restoran_max_bot/urls.py index 341e0fc..765521d 100644 --- a/restoran_max_bot/restoran_max_bot/urls.py +++ b/restoran_max_bot/restoran_max_bot/urls.py @@ -1,8 +1,12 @@ from django.contrib import admin from django.urls import path, include +from max_bot.views import promo_status, promo_activate + urlpatterns = [ # path('admin/', admin.site.urls), path('max/', include('max_bot.urls')), - path('content/', include('content_bot.urls')) + path('content/', include('content_bot.urls')), + path('promo/status//', promo_status), + path('promo/activate//', promo_activate), ]