Skip to content

Commit

Permalink
Create enums for telegram_bots app
Browse files Browse the repository at this point in the history
  • Loading branch information
EXG1O committed Sep 13, 2024
1 parent fba2259 commit e7512db
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 83 deletions.
12 changes: 3 additions & 9 deletions telegram_bots/base_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

from django_stubs_ext.db.models import TypedModelMeta

from .enums import APIRequestMethod

from collections.abc import Iterable
from typing import TYPE_CHECKING, AnyStr

Expand Down Expand Up @@ -74,17 +76,9 @@ def delete(


class AbstractAPIRequest(models.Model):
METHOD_CHOICES = [
('get', 'GET'),
('post', 'POST'),
('put', 'PUT'),
('patch', 'PATCH'),
('delete', 'DELETE'),
]

url = models.URLField(_('URL-адрес'))
method = models.CharField(
_('Метод'), max_length=6, choices=METHOD_CHOICES, default='get'
_('Метод'), max_length=6, choices=APIRequestMethod, default=APIRequestMethod.GET
)
headers = models.JSONField(_('Заголовки'), blank=True, null=True)
body = models.JSONField(_('Данные'), blank=True, null=True)
Expand Down
71 changes: 71 additions & 0 deletions telegram_bots/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from django.db.models import IntegerChoices, TextChoices
from django.utils.translation import gettext_lazy as _


class APIRequestMethod(TextChoices):
GET = 'get', 'GET'
POST = 'post', 'POST'
PUT = 'put', 'PUT'
PATCH = 'patch', 'PATCH'
DELETE = 'delete', 'DELETE'


class ConnectionHandlePosition(TextChoices):
LEFT = 'left', _('Слева')
RIGHT = 'right', _('Справа')


class ConnectionObjectType(TextChoices):
COMMAND = 'command', _('Команда')
COMMAND_KEYBOARD_BUTTON = 'command_keyboard_button', _('Кнопка клавиатуры')
CONDITION = 'condition', _('Условие')
BACKGROUND_TASK = 'background_task', _('Фоновая задача')

@staticmethod
def source_choices() -> list[tuple[str, str]]:
return [(value, value.label) for value in ConnectionObjectType]

@staticmethod
def target_choices() -> list[tuple[str, str]]:
return [
(value, value.label)
for value in ConnectionObjectType
if value
not in [
ConnectionObjectType.COMMAND_KEYBOARD_BUTTON,
ConnectionObjectType.BACKGROUND_TASK,
]
]


class KeyboardType(TextChoices):
DEFAULT = 'default', _('Обычный')
INLINE = 'inline', _('Встроенный')
PAYMENT = 'payment', _('Платёжный')


class ConditionPartType(TextChoices):
POSITIVE = '+', _('Положительный')
NEGATIVE = '-', _('Отрицательный')


class ConditionPartOperatorType(TextChoices):
EQUAL = '==', _('Равно')
NOT_EQUAL = '!=', _('Не равно')
GREATER = '>', _('Больше')
GREATER_OR_EQUAL = '>=', _('Больше или равно')
LESS = '<', _('Меньше')
LESS_OR_EQUAL = '<=', _('Меньше или равно')


class ConditionPartNextPartOperator(TextChoices):
AND = '&&', _('И')
OR = '||', _('ИЛИ')


class BackgroundTaskInterval(IntegerChoices):
DAY_1 = 1, _('1 день')
DAYS_3 = 3, _('3 дня')
DAYS_7 = 7, _('7 дней')
DAYS_14 = 14, _('14 дней')
DAYS_28 = 28, _('28 дней')
17 changes: 8 additions & 9 deletions telegram_bots/hub/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from rest_framework import serializers

from ..base_serializers import CommandMediaSerializer
from ..enums import ConnectionObjectType
from ..models import (
BackgroundTask,
BackgroundTaskAPIRequest,
Expand Down Expand Up @@ -37,12 +38,10 @@ class Meta:

class ConnectionSerializer(serializers.ModelSerializer[Connection]):
source_object_type = serializers.ChoiceField(
choices=['command', 'command_keyboard_button', 'condition', 'background_task'],
write_only=True,
choices=ConnectionObjectType.source_choices(), write_only=True
)
target_object_type = serializers.ChoiceField(
choices=['command', 'condition'],
write_only=True,
choices=ConnectionObjectType.target_choices(), write_only=True
)

class Meta:
Expand All @@ -59,15 +58,15 @@ class Meta:

def get_object_type(self, object: Model) -> str:
if isinstance(object, Command):
return 'command'
return ConnectionObjectType.COMMAND
elif isinstance(object, CommandKeyboardButton):
return 'command_keyboard_button'
return ConnectionObjectType.COMMAND_KEYBOARD_BUTTON
elif isinstance(object, Condition):
return 'condition'
return ConnectionObjectType.CONDITION
elif isinstance(object, BackgroundTask):
return 'background_task'
return ConnectionObjectType.BACKGROUND_TASK

raise ValueError('Unknown object!')
raise ValueError('Unknown object.')

def to_representation(self, instance: Connection) -> dict[str, Any]:
representation: dict[str, Any] = super().to_representation(instance)
Expand Down
66 changes: 21 additions & 45 deletions telegram_bots/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
AbstractCommandMedia,
AbstractDatabaseRecord,
)
from .enums import (
BackgroundTaskInterval,
ConditionPartNextPartOperator,
ConditionPartOperatorType,
ConditionPartType,
ConnectionHandlePosition,
KeyboardType,
)
from .hub.models import TelegramBotsHub

from requests import Response
Expand Down Expand Up @@ -184,11 +192,6 @@ def __str__(self) -> str:


class Connection(models.Model):
HANDLE_POSITION_CHOICES = [
('left', _('Слева')),
('right', _('Справа')),
]

telegram_bot = models.ForeignKey(
TelegramBot,
on_delete=models.CASCADE,
Expand All @@ -204,8 +207,8 @@ class Connection(models.Model):
source_handle_position = models.CharField(
_('Стартовая позиция коннектора'),
max_length=5,
choices=HANDLE_POSITION_CHOICES,
default='left',
choices=ConnectionHandlePosition,
default=ConnectionHandlePosition.LEFT,
)

target_content_type = models.ForeignKey(
Expand All @@ -216,8 +219,8 @@ class Connection(models.Model):
target_handle_position = models.CharField(
_('Окончательная позиция коннектора'),
max_length=5,
choices=HANDLE_POSITION_CHOICES,
default='right',
choices=ConnectionHandlePosition,
default=ConnectionHandlePosition.RIGHT,
)

class Meta(TypedModelMeta):
Expand Down Expand Up @@ -387,20 +390,14 @@ def __str__(self) -> str:


class CommandKeyboard(models.Model):
TYPE_CHOICES = [
('default', _('Обычный')),
('inline', _('Встроенный')),
('payment', _('Платёжный')),
]

command = models.OneToOneField(
'Command',
on_delete=models.CASCADE,
related_name='keyboard',
verbose_name=_('Команда'),
)
type = models.CharField(
_('Режим'), max_length=7, choices=TYPE_CHOICES, default='default'
_('Режим'), max_length=7, choices=KeyboardType, default=KeyboardType.DEFAULT
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -491,37 +488,22 @@ def __str__(self) -> str:


class ConditionPart(models.Model):
TYPE_CHOICES = [
('+', _('Положительный')),
('-', _('Отрицательный')),
]
OPERATOR_CHOICES = [
('==', _('Равно')),
('!=', _('Не равно')),
('>', _('Больше')),
('>=', _('Больше или равно')),
('<', _('Меньше')),
('<=', _('Меньше или равно')),
]
NEXT_PART_OPERATOR_CHOICES = [
('&&', _('И')),
('||', _('ИЛИ')),
]

condition = models.ForeignKey(
'Condition',
on_delete=models.CASCADE,
related_name='parts',
verbose_name=_('Условие'),
)
type = models.CharField(_('Тип'), max_length=1, choices=TYPE_CHOICES)
type = models.CharField(_('Тип'), max_length=1, choices=ConditionPartType)
first_value = models.CharField(_('Первое значение'), max_length=255)
operator = models.CharField(_('Оператор'), max_length=2, choices=OPERATOR_CHOICES)
operator = models.CharField(
_('Оператор'), max_length=2, choices=ConditionPartOperatorType
)
second_value = models.CharField(_('Второе значение'), max_length=255)
next_part_operator = models.CharField(
_('Оператор для следующей части'),
max_length=2,
choices=NEXT_PART_OPERATOR_CHOICES,
choices=ConditionPartNextPartOperator,
blank=True,
null=True,
)
Expand Down Expand Up @@ -573,21 +555,15 @@ def __str__(self) -> str:


class BackgroundTask(AbstractBlock):
INTERVAL_CHOICES = [
(1, _('1 день')),
(3, _('3 дня')),
(7, _('7 дней')),
(14, _('14 дней')),
(28, _('28 дней')),
]

telegram_bot = models.ForeignKey(
TelegramBot,
on_delete=models.CASCADE,
related_name='background_tasks',
verbose_name=_('Telegram бот'),
)
interval = models.PositiveSmallIntegerField(_('Интервал'), choices=INTERVAL_CHOICES)
interval = models.PositiveSmallIntegerField(
_('Интервал'), choices=BackgroundTaskInterval
)
source_connections = None

if TYPE_CHECKING:
Expand Down
42 changes: 22 additions & 20 deletions telegram_bots/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from .base_models import AbstractCommandMedia
from .base_serializers import CommandMediaSerializer, DiagramSerializer
from .enums import ConnectionObjectType
from .models import (
BackgroundTask,
BackgroundTaskAPIRequest,
Expand Down Expand Up @@ -116,12 +117,10 @@ class ConnectionSerializer(
TelegramBotContextMixin, serializers.ModelSerializer[Connection]
):
source_object_type = serializers.ChoiceField(
choices=['command', 'command_keyboard_button', 'condition', 'background_task'],
write_only=True,
choices=ConnectionObjectType.source_choices(), write_only=True
)
target_object_type = serializers.ChoiceField(
choices=['command', 'condition'],
write_only=True,
choices=ConnectionObjectType.target_choices(), write_only=True
)

class Meta:
Expand All @@ -137,52 +136,55 @@ class Meta:
]

def get_object(self, object_type: str, object_id: int) -> Model:
if object_type == 'command':
if object_type == ConnectionObjectType.COMMAND:
try:
return self.telegram_bot.commands.get(id=object_id)
except Command.DoesNotExist:
raise serializers.ValidationError(_('Команда не найдена!'))
elif object_type == 'command_keyboard_button':
raise serializers.ValidationError(_('Команда не найдена.'))
elif object_type == ConnectionObjectType.COMMAND_KEYBOARD_BUTTON:
try:
return CommandKeyboardButton.objects.get(
keyboard__command__telegram_bot=self.telegram_bot, id=object_id
)
except CommandKeyboardButton.DoesNotExist:
raise serializers.ValidationError(
_('Кнопка клавиатуры команды не найдена!')
_('Кнопка клавиатуры команды не найдена.')
)
elif object_type == 'condition':
elif object_type == ConnectionObjectType.CONDITION:
try:
return self.telegram_bot.conditions.get(id=object_id)
except Condition.DoesNotExist:
raise serializers.ValidationError(_('Условие не найдено!'))
elif object_type == 'background_task':
raise serializers.ValidationError(_('Условие не найдено.'))
elif object_type == ConnectionObjectType.BACKGROUND_TASK:
try:
return self.telegram_bot.background_tasks.get(id=object_id)
except BackgroundTask.DoesNotExist:
raise serializers.ValidationError(_('Фоновая задача не найдена!'))
raise serializers.ValidationError(_('Фоновая задача не найдена.'))

raise ValueError('Unknown object type!')
raise ValueError('Unknown object type.')

def get_object_type(self, object: Model) -> str:
if isinstance(object, Command):
return 'command'
return ConnectionObjectType.COMMAND
elif isinstance(object, CommandKeyboardButton):
return 'command_keyboard_button'
return ConnectionObjectType.COMMAND_KEYBOARD_BUTTON
elif isinstance(object, Condition):
return 'condition'
return ConnectionObjectType.CONDITION
elif isinstance(object, BackgroundTask):
return 'background_task'
return ConnectionObjectType.BACKGROUND_TASK

raise ValueError('Unknown object!')
raise ValueError('Unknown object.')

def validate(self, data: dict[str, Any]) -> dict[str, Any]:
source_object_type: str = data.pop('source_object_type')
target_object_type: str = data.pop('target_object_type')

if source_object_type == 'command' and target_object_type == 'command':
if (
source_object_type == ConnectionObjectType.COMMAND
and target_object_type == ConnectionObjectType.COMMAND
):
raise serializers.ValidationError(
_('Нельзя подключить команду к другой команде!')
_('Нельзя подключить команду к другой команде.')
)

data['source_object'] = self.get_object(
Expand Down

0 comments on commit e7512db

Please sign in to comment.