Compare commits

...

2 Commits

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

@ -5,4 +5,5 @@ urlpatterns = [
path('api/v1/<str:token>', api_start_max_v1),
path('iiko/webhook/<str:token>', iiko_webhook),
path('iiko/send-message/<str:token>', iiko_send_message),
]

@ -1,15 +1,15 @@
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
from restoran_max_bot.common import common_get_contact
from restoran_max_bot.common import common_get_contact, common_check_registration
from restoran_max_bot.settings import DEBUG
from restoran_max_bot.utils import is_json, has_key
@ -72,13 +72,6 @@ def api_start_max_v1(request, token, **kwargs):
rt = {'success': False, 'error': 'data update_type not found', 'data': ''}
return JsonResponse(rt, status=200)
# обработчик промо кодов с запросов
# https://dev.max.ru/docs/chatbots/bots-coding/prepare
# https://max.ru/id032606883607_2_bot?start=source_site
if data.get("payload", None):
print(data['payload'])
bot_promo(client=client, message=data, settings_max=settings_max)
# получение сообщения из бота
if data['update_type'] == 'message_created':
bot_message(client=client, message=data, settings_max=settings_max, message_type='message_created')
@ -88,6 +81,12 @@ def api_start_max_v1(request, token, **kwargs):
# start - запуск бота
if data['update_type'] == 'bot_started':
# https://dev.max.ru/docs/chatbots/bots-coding/prepare
# https://max.ru/id032606883607_2_bot?start=source_site
# роверка на промокод
if data.get("payload", None):
bot_promo(client=client, message=data, settings_max=settings_max)
if not common_check_registration(client=client, chat_id=data['chat_id']):
bot_started(client=client, message=data, settings=settings_max)
# выход из бота
@ -136,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"""
<html>
<body>
<h1>Промокод: {promo.promo}</h1>
<p>ID чата: {promo.chat_id}</p>
<p>Статус: <strong>Использован</strong></p>
<p>Время использования: {promo.used_at}</p>
</body>
</html>
"""
return HttpResponse(html)
# Если не использован, показываем кнопку с запросом PIN-кода
html = f"""
<html>
<body>
<h1>Промокод: {promo.promo}</h1>
<p>ID чата: {promo.chat_id}</p>
<p>Статус: <strong style="color:green;">Не использован</strong></p>
<button onclick="activate()">Активировать</button>
<script>
function activate() {{
var pin = prompt("Введите PIN-код администратора:");
if (pin) {{
fetch('/promo/activate/{promo_code}/{chat_id}', {{
method: 'POST',
headers: {{'Content-Type': 'application/json'}},
body: JSON.stringify({{pin: pin}})
}})
.then(res => res.json())
.then(data => {{
alert(data.message);
if (data.success) location.reload();
}});
}}
}}
</script>
</body>
</html>
"""
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': 'Промокод активирован, клиент получил уведомление'})

@ -257,32 +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 data:
# Генерация qr кода URL в параметрах телефон, промокод
url_promo = f"https://maxbot.telefon-ip.ru/promo/?promo={promo}&chat-id={chat_id}"
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}")
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-код')
# Отправка данных
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:
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)
# сохранение в meta информации о коде
# ПРОВЕРКА НА РЕГИСТРАЦИЮ ???
return True

@ -21,8 +21,7 @@ def bot_started(client: Client, message: dict, settings: dict):
text='Согласен на обработку персональных данных.')
return True
# проверка есть ли регистрация клиента номер телефона
# проверка есть ли регистрация клиента номер телефона, запись создается после отправки ноера телефона
def get_registration_phone(client: Client, chat_id: str, settings: dict):
contact = common_get_contact(client=client, uid_client=chat_id)
if not contact:
@ -41,31 +40,6 @@ def get_registration_phone(client: Client, chat_id: str, settings: dict):
return False
return contact
# проверка есть ли регистрация клиента день рождение
def get_registration_birthday(client: Client, chat_id: str, settings: dict):
contact = common_get_contact(client=client, uid_client=chat_id)
if not contact:
data = common_get_data(client=client, key='start'.lower())
if data:
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['token'], img=url, message=dt.descr)
else:
maxbot_send_text_message(chat_id=chat_id, max_token=settings['token'], message=dt.descr)
if dt.url:
maxbot_send_text_message(chat_id=chat_id, max_token=settings['token'], message=dt.url)
maxbot_get_phone(chat_id=chat_id, max_token=settings['token'], text='Подтвердите согласие')
return False
if not contact.field1:
return False
return contact
# проверка регистрации в боте (что все данные получены)
def check_registration(client: Client, chat_id: str, message: dict, settings: dict):
contact = get_registration_phone(client=client, chat_id=chat_id, settings=settings)

@ -88,3 +88,15 @@ def send_message_all_manager(client: Client, message: str):
return response
def common_check_registration(client: Client, chat_id: str) -> None | bool | Contact:
# функция проверяет все ли данные заполнены клиентом
contact = common_get_contact(client=client, uid_client=chat_id)
if not contact:
return None
if contact.field1 is None or contact.field1 == '':
return None
if contact.field2 is None or contact.field2 == '':
return None
return contact

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

@ -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/<str:promo_code>/<str:chat_id>', promo_status),
path('promo/activate/<str:promo_code>/<str:chat_id>', promo_activate),
]

Loading…
Cancel
Save