Files
tg_autopost/bot/models.py
2025-08-08 11:37:11 +09:00

164 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# bot/models.py
from django.db import models
from django.utils import timezone
class TelegramBot(models.Model):
"""
Карточка бота. Можно держать несколько активных одновременно.
"""
name = models.CharField(
max_length=100,
help_text="Произвольное имя бота в проекте",
)
username = models.CharField(
max_length=100,
blank=True,
help_text="@username в Telegram",
)
token = models.CharField(
max_length=200,
help_text="Токен от @BotFather",
)
is_active = models.BooleanField(
default=True,
help_text="Если включен — может быть запущен runbots",
)
class Meta:
verbose_name = "Telegram бот"
verbose_name_plural = "Telegram боты"
ordering = ("-is_active", "name")
def __str__(self) -> str:
return f"{self.name} ({self.username or 'no-username'})"
class BotConfig(models.Model):
"""
Конфигурация для конкретного бота (парсинг, allowed_updates, админы, вебхук).
Делается OneToOne, но без опоры на обратный атрибут .config у TelegramBot.
"""
bot = models.OneToOneField(
TelegramBot,
on_delete=models.CASCADE,
help_text="Какому боту принадлежит конфигурация",
)
parse_mode = models.CharField(
max_length=20,
default="HTML",
choices=[("HTML", "HTML"), ("MarkdownV2", "MarkdownV2"), ("None", "None")],
help_text="Режим парсинга сообщений (или None для обычного текста)",
)
allowed_updates = models.JSONField(
default=list,
blank=True,
help_text="Список типов апдейтов, например ['message','my_chat_member','chat_member']",
)
admin_user_ids = models.JSONField(
default=list,
blank=True,
help_text="Список Telegram user_id, имеющих права администратора",
)
webhook_url = models.URLField(
blank=True,
default="",
help_text="URL вебхука (если используете вебхуки)",
)
use_webhook = models.BooleanField(
default=False,
help_text="Включить режим webhook вместо polling",
)
class Meta:
verbose_name = "Конфигурация бота"
verbose_name_plural = "Конфигурации ботов"
def __str__(self) -> str:
return f"Config for {self.bot}"
class TelegramChat(models.Model):
"""
Чаты храним ПО БОТУ. Один и тот же chat_id TG может встречаться у разных ботов,
поэтому уникальность задаётся на (bot, chat_id).
Важно: не используем поле с именем 'id' под chat_id Telegram, чтобы не ломать Django.
Стандартный PK (BigAutoField) оставляем как есть.
"""
CHAT_TYPES = [
("private", "private"),
("group", "group"),
("supergroup", "supergroup"),
("channel", "channel"),
]
bot = models.ForeignKey(
TelegramBot,
on_delete=models.CASCADE,
related_name="chats",
help_text="К какому боту относится этот чат",
)
chat_id = models.BigIntegerField(
help_text="Идентификатор чата в Telegram (может быть до ~52 бит)",
)
type = models.CharField(
max_length=20,
choices=CHAT_TYPES,
help_text="Тип чата",
)
title = models.CharField(
max_length=255,
blank=True,
default="",
help_text="Название (для групп/каналов)",
)
username = models.CharField(
max_length=255,
blank=True,
default="",
help_text="Username чата/канала (если есть)",
)
# Статус участия бота
is_member = models.BooleanField(
default=True,
help_text="Состоит ли бот в чате сейчас",
)
joined_at = models.DateTimeField(
default=timezone.now,
help_text="Когда бот был добавлен",
)
left_at = models.DateTimeField(
null=True,
blank=True,
help_text="Когда бот покинул чат",
)
# Метаданные активности
last_message_at = models.DateTimeField(
null=True,
blank=True,
help_text="Когда последний раз видели сообщение в этом чате",
)
class Meta:
verbose_name = "Telegram чат"
verbose_name_plural = "Telegram чаты"
constraints = [
models.UniqueConstraint(
fields=["bot", "chat_id"],
name="uniq_bot_chat",
),
]
indexes = [
models.Index(fields=["bot", "chat_id"]),
models.Index(fields=["bot", "type"]),
models.Index(fields=["bot", "is_member"]),
]
ordering = ("-is_member", "-joined_at")
def __str__(self) -> str:
base = self.title or self.username or str(self.chat_id)
return f"{base} [{self.type}]"