Взаимодействие через виджет (widget_channel)🔗
Назначение🔗
Приложение widget_channel отвечает за реализацию веб-виджета, который можно встроить на сторонние сайты для общения с пользователями. Система включает:
- профили виджетов (
WidgetSettings) с параметрами отображения;
Внимание
Надо бы поменять название на WidgetProfile как везде, а то от варианта стиля осталось
- управление доменами;
- выбор иконок (кастомных и базовых);
- сохранение чатов и сообщений;
- API для CRUD-операций, загрузки и отображения иконок;
- защиту по домену.
Все данные предоставляются через API под префиксом /api/v1/widget/.
Основные модели и сущности🔗
WidgetSettings🔗
Наследуется от BaseProfile.
class WidgetSettings(BaseProfile):
tg_token = models.CharField(...)
manager_tg_id = ArrayField(...)
welcome_text = models.TextField(...)
start_hints = ArrayField(...)
widget_left = models.BooleanField(...)
icon = models.ForeignKey(UserIcon, ...)
base_icon = models.ForeignKey(BaseIcon, ...)
| Поле | Назначение |
|---|---|
tg_token | Токен Telegram-бота для оповещений |
manager_tg_id | Telegram ID менеджеров, получающих уведомления |
welcome_text | Приветствие при открытии чата |
start_hints | Стартовые подсказки в окне чата |
widget_left | Расположение на экране (True = слева) |
icon | Пользовательская иконка (приоритет ниже) |
base_icon | Базовая иконка (имеет приоритет, если выбраны обе (что по идее невозможно)) |
При выборе обеих иконок используется
base_icon,iconавтоматически сбрасывается.
Domain🔗
class Domain(models.Model):
owner = models.ForeignKey(WidgetSettings, ...)
name = models.CharField(unique=True, ...)
| Поле | Назначение |
|---|---|
name | Домен, на котором разрешено использовать скрипт |
При инициализации виджета клиентская часть передаёт домен, и он сверяется с
Domain.name.
UserIcon / BaseIcon🔗
class UserIcon(models.Model):
owner = models.ForeignKey(CustomUser, ...)
url = models.CharField(...)
UserIcon— иконки, загружаемые пользователями. Доступны только владельцу;BaseIcon— предзагруженные иконки, доступны всем.
Chats🔗
class Chats(models.Model):
widget_owner = models.ForeignKey(WidgetSettings, ...)
user_id = models.CharField(unique=True, ...)
date_last_message = models.DateTimeField(...)
is_favorite = models.BooleanField(...)
note = models.TextField(...)
user_id— ID клиента (анонимный посетитель), хранимый на фронте;widget_owner.user— владелец чата. Все фильтрации выполняются поwidget_owner__user.
Messages🔗
class Messages(models.Model):
chat = models.ForeignKey(Chats, ...)
message = models.TextField(...)
sender = models.CharField(...)
date = models.DateTimeField(...)
Сообщения сохраняются автоматически при обращении клиента к виджету. Используются в API и в админке.
Связи и использование🔗
WidgetSettingsсоздаётся вручную через API или админку;Domainдобавляется для защиты по источнику скрипта;- При инициализации скрипт обращается к
data_service, который проверяет:- домен;
- активность профиля;
- параметры отображения (
welcome_text,icon, и т.д.);
ChatsиMessagesформируются в процессе общения с виджетом;- Все обращения к данным через API фильтруются по
request.user.
Особенности🔗
base_iconимеет приоритет надicon— логика enforced на уровне сериализатора;- Все иконки можно загружать, переименовывать и удалять (при удалении физический файл стирается);
- Чаты привязаны к
WidgetSettings, и фильтруются по егоuser; - Виджеты, домены, иконки — строго ограничены по пользователю, доступ к чужим объектам невозможен;
- Telegram и OpenAI-поля заполняются вручную и используются микросервисом
data_service; - В админке отключено удаление виджетов, ограничено добавление, и скрыты неиспользуемые поля (
BaseProfile).
Приписка
Изначально проект был заточен только под виджет, после переделки на новый вариант основной упор был на интеграции ватсап, вк и тд. когда принялся за виджет то BaseProfile был не адаптирован под виджет и там были лишние поля, поэтому я скрыл лишние поля из админки, в будущем может быть что то придумаю
Админка🔗
WidgetSettings🔗
- Поля из
BaseProfile+ специфичные поля только для виджета; serviceнельзя изменить после создания;DomainInlineвстроен в форму;- Удаление отключено (
has_delete_permission = False).
Chats🔗
- Содержит
MessagesInline; - Поддерживает фильтрацию по дате, избранному, владельцу;
- Заметки (
note) можно редактировать.
Domains, Icons🔗
- Все стандартные: фильтры, поиск, отображение;
- Для
UserIconреализован жёсткий контроль по владельцу.
API🔗
Общая информация🔗
Все эндпоинты доступны по префиксу: /api/v1/widget/ Требуется авторизация по сессии (sessionid + CSRF).
Совет
Подробную документацию энпоинтов можете найти в разделе - API
Эндпоинты🔗
Виджеты🔗
POST /api/v1/widget/settings/create/
PATCH /api/v1/widget/settings/<widget_id>/update/
DELETE /api/v1/widget/settings/<widget_id>/delete/
GET /api/v1/widget/info/
GET /api/v1/widget/info/<widget_id>/
Домены🔗
POST /api/v1/widget/settings/<widget_id>/domains/create/
DELETE /api/v1/widget/domains/<domain_id>/delete/
Иконки🔗
GET /api/v1/widget/settings/user-icons/
GET /api/v1/widget/settings/base-icons/
POST /api/v1/widget/settings/user-icon/upload/
PATCH /api/v1/widget/settings/user-icons/<icon_id>/update-name/
DELETE /api/v1/widget/settings/user-icons/<icon_id>/
Чаты и сообщения🔗
Использование🔗
- Фронтенд пользователя использует все CRUD-эндпоинты для управления виджетами, доменами, иконками;
- Интерфейс админки/личного кабинета обращается к чату и сообщениям;
- data_service — использует модель
WidgetSettingsдля получения параметров при генерации ответа и проверки авторизации.