Исправлено: встраивание веб-версий мессенджеров через iframe вместо интеграции. Удалена проблемная миграция.

This commit is contained in:
admin i 2025-11-30 10:39:09 +03:00
parent 95739f287b
commit 750a2c5da8
8 changed files with 170 additions and 1227 deletions

View File

@ -1,88 +0,0 @@
# Быстрый старт: Настройка интеграции мессенджеров
## Что было добавлено:
✅ **3 новые модели базы данных:**
- `MessengerIntegration` - настройки подключения
- `MessengerAccount` - привязка аккаунтов сотрудников
- `MessengerMessage` - синхронизация сообщений
✅ **Админ-панель** для управления интеграциями
✅ **Страницы мессенджеров** с инструкциями
## Как начать:
### 1. Откройте админ-панель
Перейдите: http://localhost:9000/admin/communications/
Вы увидите новые разделы:
- **Интеграции с мессенджерами**
- **Аккаунты в мессенджерах**
- **Сообщения из мессенджеров**
### 2. Создайте интеграцию (пример для Telegram)
1. Нажмите "Интеграции с мессенджерами" → "Добавить"
2. Заполните:
- **Тип мессенджера**: Telegram
- **Включена**: ✓
- **Статус**: Active
- **API ключ**: (получите от @BotFather в Telegram)
3. Сохраните
### 3. Проверьте результат
Перейдите в раздел "Мои чаты":
- В боковой панели появились иконки мессенджеров
- Кликните на иконку Telegram
- Вы увидите страницу с инструкциями
Если вы администратор:
- Появится кнопка "Настроить интеграцию"
- Будут видны подробные инструкции
## Для администраторов
### Получение API ключей:
**Telegram (самый простой):**
1. Откройте @BotFather в Telegram
2. Отправьте `/newbot`
3. Следуйте инструкциям
4. Скопируйте Bot Token
5. Вставьте в админ-панель
**WhatsApp Business API:**
1. https://business.whatsapp.com/
2. Создайте приложение в Facebook for Developers
3. Получите Access Token
**WeChat:**
1. https://mp.weixin.qq.com/
2. Зарегистрируйте Official Account
3. Получите AppID и AppSecret
### Полная документация
📖 См. файл `MESSENGER_INTEGRATION_GUIDE.md` для детальных инструкций по:
- Настройке webhooks
- Привязке аккаунтов сотрудников
- Синхронизации сообщений
- Безопасности
- Мониторингу
- Troubleshooting
## Следующие шаги (для разработки)
Для полноценной работы интеграций потребуется реализовать:
1. **Webhook handlers** - обработка входящих сообщений
2. **Sync services** - синхронизация сообщений
3. **API endpoints** - для отправки сообщений
4. **Celery tasks** - фоновая синхронизация
Базовая инфраструктура готова, можно начинать интеграцию!

View File

@ -1,316 +0,0 @@
# Настройка интеграции мессенджеров
Этот документ описывает процесс настройки интеграции с WhatsApp, Telegram и WeChat.
## Архитектура
Система интеграции состоит из трех основных компонентов:
1. **MessengerIntegration** - настройки подключения к мессенджеру
2. **MessengerAccount** - привязка аккаунтов сотрудников
3. **MessengerMessage** - синхронизация сообщений
## Шаги настройки
### 1. Доступ к админ-панели
Перейдите в Django Admin: `http://your-domain/admin/communications/`
Вы увидите три новых раздела:
- Интеграции с мессенджерами
- Аккаунты в мессенджерах
- Сообщения из мессенджеров
### 2. Настройка WhatsApp
#### 2.1. Получение API ключей
**Вариант A: WhatsApp Business API (официальный)**
1. Зарегистрируйтесь на https://business.whatsapp.com/
2. Создайте приложение в Facebook for Developers
3. Получите `WhatsApp Business Account ID` и `Access Token`
**Вариант B: WhatsApp Web API (неофициальный, через Baileys/Whatsapp-web.js)**
1. Используйте библиотеку для Node.js
2. Настройте webhook для получения сообщений
3. Получите QR-код для авторизации
#### 2.2. Настройка в системе
1. Откройте "Интеграции с мессенджерами" → "Добавить"
2. Выберите тип: **WhatsApp**
3. Заполните поля:
- **Включена**: ✓
- **Статус**: Active
- **API ключ**: `<ваш Access Token>`
- **Webhook URL**: `https://your-domain/communications/webhooks/whatsapp/`
4. В разделе "Дополнительные настройки" (JSON):
```json
{
"phone_number_id": "YOUR_PHONE_NUMBER_ID",
"business_account_id": "YOUR_BUSINESS_ACCOUNT_ID",
"verify_token": "YOUR_WEBHOOK_VERIFY_TOKEN"
}
```
#### 2.3. Настройка webhook на стороне WhatsApp
1. В Facebook for Developers → WhatsApp → Configuration
2. Укажите webhook URL: `https://your-domain/communications/webhooks/whatsapp/`
3. Укажите Verify Token (из настроек выше)
4. Подпишитесь на события: `messages`, `message_status`
### 3. Настройка Telegram
#### 3.1. Создание бота
1. Найдите @BotFather в Telegram
2. Отправьте команду `/newbot`
3. Следуйте инструкциям для создания бота
4. Получите **Bot Token** (формат: `123456789:ABCdefGHIjklMNOpqrsTUVwxyz`)
#### 3.2. Настройка в системе
1. Откройте "Интеграции с мессенджерами" → "Добавить"
2. Выберите тип: **Telegram**
3. Заполните поля:
- **Включена**: ✓
- **Статус**: Active
- **API ключ**: `<Bot Token от BotFather>`
- **Webhook URL**: `https://your-domain/communications/webhooks/telegram/`
4. В разделе "Дополнительные настройки":
```json
{
"bot_username": "your_bot_name",
"allowed_updates": ["message", "edited_message", "callback_query"]
}
```
#### 3.3. Установка webhook
Выполните запрос (замените токен):
```bash
curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-domain/communications/webhooks/telegram/"}'
```
### 4. Настройка WeChat
#### 4.1. Регистрация WeChat Official Account
1. Зарегистрируйтесь на https://mp.weixin.qq.com/
2. Создайте Official Account
3. Получите `AppID` и `AppSecret`
#### 4.2. Настройка в системе
1. Откройте "Интеграции с мессенджерами" → "Добавить"
2. Выберите тип: **WeChat**
3. Заполните поля:
- **Включена**: ✓
- **Статус**: Active
- **API ключ**: `<AppID>`
- **API секрет**: `<AppSecret>`
- **Webhook URL**: `https://your-domain/communications/webhooks/wechat/`
4. В разделе "Дополнительные настройки":
```json
{
"token": "YOUR_TOKEN",
"encoding_aes_key": "YOUR_ENCODING_AES_KEY"
}
```
## Привязка аккаунтов сотрудников
После настройки интеграции нужно привязать аккаунты сотрудников:
### Автоматическая привязка
Сотрудники могут сами привязать аккаунты:
1. Перейти в профиль → "Мессенджеры"
2. Выбрать мессенджер
3. Следовать инструкциям (QR-код, код подтверждения и т.д.)
### Ручная привязка (админ)
1. Откройте "Аккаунты в мессенджерах" → "Добавить"
2. Выберите пользователя
3. Выберите интеграцию
4. Укажите:
- **External ID**: ID пользователя в мессенджере
- **External Username**: Имя/никнейм
- **Phone Number**: Телефон (для WhatsApp)
5. Установите галочку "Подтвержден"
## Синхронизация сообщений
### Настройка Celery задач
Добавьте в `celery.py`:
```python
from celery.schedules import crontab
app.conf.beat_schedule = {
'sync-messenger-messages': {
'task': 'communications.tasks.sync_messenger_messages',
'schedule': 60.0, # каждую минуту
},
}
```
### Ручная синхронизация
Через Django shell:
```python
from communications.services.messenger_sync import MessengerSyncService
# Синхронизация всех мессенджеров
sync_service = MessengerSyncService()
sync_service.sync_all()
# Синхронизация конкретного мессенджера
sync_service.sync_messenger('whatsapp')
```
## Webhook эндпоинты
Система автоматически создает эндпоинты для получения входящих сообщений:
- **WhatsApp**: `POST /communications/webhooks/whatsapp/`
- **Telegram**: `POST /communications/webhooks/telegram/`
- **WeChat**: `POST /communications/webhooks/wechat/`
Эти URL должны быть доступны извне (HTTPS обязателен для production).
## Безопасность
### Шифрование API ключей
В production используйте `django-cryptography` для шифрования:
```python
# settings.py
INSTALLED_APPS = [
...
'django_cryptography',
]
# Генерация ключа
from cryptography.fernet import Fernet
FIELD_ENCRYPTION_KEY = Fernet.generate_key().decode()
```
Обновите модель:
```python
from django_cryptography.fields import encrypt
class MessengerIntegration(models.Model):
api_key = encrypt(models.CharField(max_length=500))
api_secret = encrypt(models.CharField(max_length=500))
```
### Проверка подписи webhook
Всегда проверяйте подпись входящих запросов:
```python
# views.py
def verify_whatsapp_signature(request):
signature = request.headers.get('X-Hub-Signature-256')
# Проверка HMAC
...
```
## Мониторинг
### Просмотр статистики
В админ-панели "Интеграции с мессенджерами" отображается:
- Количество отправленных сообщений
- Количество полученных сообщений
- Время последней синхронизации
- Последняя ошибка (если есть)
### Логирование
Все операции логируются:
```python
import logging
logger = logging.getLogger('communications.messenger')
# В settings.py
LOGGING = {
'loggers': {
'communications.messenger': {
'level': 'INFO',
'handlers': ['file'],
},
},
}
```
## Troubleshooting
### Проблема: Webhook не получает сообщения
1. Проверьте, что URL доступен извне:
```bash
curl https://your-domain/communications/webhooks/telegram/
```
2. Проверьте SSL сертификат (должен быть валидным)
3. Проверьте логи Django:
```bash
tail -f logs/django.log | grep webhook
```
### Проблема: Сообщения не синхронизируются
1. Проверьте статус интеграции (должен быть "Active")
2. Проверьте поле "Последняя ошибка"
3. Запустите синхронизацию вручную через shell
4. Проверьте Celery tasks (если используется)
### Проблема: Неверный API ключ
1. Перегенерируйте ключ в соответствующем сервисе
2. Обновите в админ-панели
3. Измените статус на "Active" после обновления
## Дальнейшее развитие
### Планируемые функции
- [ ] Групповые чаты в мессенджерах
- [ ] Отправка медиа-файлов
- [ ] Голосовые сообщения
- [ ] Статусы доставки
- [ ] Typing indicators
- [ ] Реакции на сообщения
- [ ] Шаблоны сообщений для WhatsApp Business
### API endpoints для разработчиков
```
POST /api/v1/messenger/send/
GET /api/v1/messenger/accounts/
GET /api/v1/messenger/messages/
POST /api/v1/messenger/link-account/
```
Документация API: `https://your-domain/api/docs/`
## Поддержка
При возникновении проблем:
1. Проверьте документацию мессенджера
2. Проверьте логи системы
3. Обратитесь к системному администратору

View File

@ -8,9 +8,6 @@ from .models import (
Message,
MessageAttachment,
MessageReply,
MessengerIntegration,
MessengerAccount,
MessengerMessage,
)
@ -172,176 +169,3 @@ class CrossChatMessageAdmin(admin.ModelAdmin):
list_filter = ("status", "requires_moderation", "sent_at")
search_fields = ("sender__last_name", "target_chat__name")
ordering = ("-sent_at",)
# ===== АДМИН-ПАНЕЛЬ ДЛЯ ИНТЕГРАЦИЙ С МЕССЕНДЖЕРАМИ =====
@admin.register(MessengerIntegration)
class MessengerIntegrationAdmin(admin.ModelAdmin):
list_display = (
"messenger_type",
"is_enabled",
"status",
"messages_sent",
"messages_received",
"last_sync_at",
"updated_at"
)
list_filter = ("messenger_type", "is_enabled", "status")
search_fields = ("messenger_type",)
ordering = ("messenger_type",)
fieldsets = (
("Основная информация", {
"fields": ("messenger_type", "is_enabled", "status")
}),
("API Настройки", {
"fields": ("api_key", "api_secret", "webhook_url", "settings"),
"classes": ("collapse",)
}),
("Статистика", {
"fields": (
"messages_sent",
"messages_received",
"last_sync_at",
"last_error"
),
"classes": ("collapse",)
}),
("Системная информация", {
"fields": ("created_at", "updated_at"),
"classes": ("collapse",)
}),
)
readonly_fields = (
"messages_sent",
"messages_received",
"last_sync_at",
"created_at",
"updated_at"
)
def get_readonly_fields(self, request, obj=None):
if obj and obj.status == 'active':
return self.readonly_fields + ("messenger_type",)
return self.readonly_fields
@admin.register(MessengerAccount)
class MessengerAccountAdmin(admin.ModelAdmin):
list_display = (
"user",
"integration",
"external_username",
"phone_number",
"is_verified",
"is_active",
"updated_at"
)
list_filter = (
"integration__messenger_type",
"is_verified",
"is_active"
)
search_fields = (
"user__last_name",
"user__first_name",
"external_username",
"phone_number",
"external_id"
)
ordering = ("-created_at",)
fieldsets = (
("Пользователь", {
"fields": ("user", "integration")
}),
("Данные в мессенджере", {
"fields": (
"external_id",
"external_username",
"phone_number"
)
}),
("Статус", {
"fields": ("is_verified", "is_active")
}),
("Дополнительно", {
"fields": ("metadata",),
"classes": ("collapse",)
}),
("Системная информация", {
"fields": ("created_at", "updated_at"),
"classes": ("collapse",)
}),
)
readonly_fields = ("created_at", "updated_at")
@admin.register(MessengerMessage)
class MessengerMessageAdmin(admin.ModelAdmin):
list_display = (
"id",
"integration",
"direction",
"status",
"sender_account",
"content_preview",
"external_timestamp",
"synced_at"
)
list_filter = (
"integration__messenger_type",
"direction",
"status",
"external_timestamp"
)
search_fields = (
"external_id",
"content",
"sender_account__external_username"
)
ordering = ("-external_timestamp",)
fieldsets = (
("Основная информация", {
"fields": (
"integration",
"internal_message",
"external_id"
)
}),
("Участники", {
"fields": (
"sender_account",
"recipient_account",
"direction"
)
}),
("Содержимое", {
"fields": ("content", "attachments")
}),
("Статус и время", {
"fields": (
"status",
"external_timestamp",
"synced_at"
)
}),
("Дополнительно", {
"fields": ("raw_data",),
"classes": ("collapse",)
}),
)
readonly_fields = ("synced_at",)
def content_preview(self, obj):
"""Превью содержимого сообщения"""
if len(obj.content) > 50:
return obj.content[:50] + "..."
return obj.content
content_preview.short_description = "Содержимое"

View File

@ -850,289 +850,3 @@ class ChatMembership(models.Model):
def __str__(self):
return f"{self.user} в {self.chat} ({self.get_role_display()})"
# ===== МОДЕЛИ ДЛЯ ИНТЕГРАЦИИ МЕССЕНДЖЕРОВ =====
class MessengerIntegration(models.Model):
"""
Настройки интеграции с внешними мессенджерами (WhatsApp, Telegram, WeChat)
"""
MESSENGER_TYPES = [
('whatsapp', 'WhatsApp'),
('telegram', 'Telegram'),
('wechat', 'WeChat'),
]
STATUS_CHOICES = [
('inactive', 'Не активна'),
('active', 'Активна'),
('error', 'Ошибка'),
]
messenger_type = models.CharField(
max_length=20,
choices=MESSENGER_TYPES,
unique=True,
verbose_name="Тип мессенджера"
)
is_enabled = models.BooleanField(
default=False,
verbose_name="Включена"
)
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='inactive',
verbose_name="Статус"
)
# API настройки (зашифрованы в production)
api_key = models.CharField(
max_length=500,
blank=True,
verbose_name="API ключ"
)
api_secret = models.CharField(
max_length=500,
blank=True,
verbose_name="API секрет"
)
webhook_url = models.URLField(
max_length=500,
blank=True,
verbose_name="Webhook URL"
)
# Дополнительные настройки (JSON)
settings = models.JSONField(
default=dict,
blank=True,
verbose_name="Дополнительные настройки"
)
# Статистика
last_sync_at = models.DateTimeField(
null=True,
blank=True,
verbose_name="Последняя синхронизация"
)
messages_sent = models.IntegerField(
default=0,
verbose_name="Отправлено сообщений"
)
messages_received = models.IntegerField(
default=0,
verbose_name="Получено сообщений"
)
last_error = models.TextField(
blank=True,
verbose_name="Последняя ошибка"
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Создано")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Обновлено")
class Meta:
verbose_name = "Интеграция с мессенджером"
verbose_name_plural = "Интеграции с мессенджерами"
indexes = [
models.Index(fields=['messenger_type', 'is_enabled']),
models.Index(fields=['status']),
]
def __str__(self):
return f"{self.get_messenger_type_display()} - {self.get_status_display()}"
class MessengerAccount(models.Model):
"""
Привязка аккаунта сотрудника к мессенджеру
"""
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='messenger_accounts',
verbose_name="Пользователь"
)
integration = models.ForeignKey(
MessengerIntegration,
on_delete=models.CASCADE,
related_name='accounts',
verbose_name="Интеграция"
)
# ID пользователя в мессенджере
external_id = models.CharField(
max_length=200,
verbose_name="ID в мессенджере"
)
# Имя/никнейм в мессенджере
external_username = models.CharField(
max_length=200,
blank=True,
verbose_name="Имя в мессенджере"
)
# Телефон (для WhatsApp)
phone_number = models.CharField(
max_length=20,
blank=True,
verbose_name="Номер телефона"
)
is_verified = models.BooleanField(
default=False,
verbose_name="Подтвержден"
)
is_active = models.BooleanField(
default=True,
verbose_name="Активен"
)
# Дополнительные данные
metadata = models.JSONField(
default=dict,
blank=True,
verbose_name="Метаданные"
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Создано")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Обновлено")
class Meta:
verbose_name = "Аккаунт в мессенджере"
verbose_name_plural = "Аккаунты в мессенджерах"
unique_together = [('integration', 'external_id')]
indexes = [
models.Index(fields=['user', 'integration']),
models.Index(fields=['external_id']),
models.Index(fields=['phone_number']),
]
def __str__(self):
return f"{self.user} - {self.integration.get_messenger_type_display()} ({self.external_username or self.external_id})"
class MessengerMessage(models.Model):
"""
Синхронизированные сообщения из внешних мессенджеров
"""
DIRECTION_CHOICES = [
('incoming', 'Входящее'),
('outgoing', 'Исходящее'),
]
STATUS_CHOICES = [
('pending', 'В ожидании'),
('sent', 'Отправлено'),
('delivered', 'Доставлено'),
('read', 'Прочитано'),
('failed', 'Ошибка'),
]
integration = models.ForeignKey(
MessengerIntegration,
on_delete=models.CASCADE,
related_name='messenger_messages',
verbose_name="Интеграция"
)
# Связь с внутренним сообщением (если синхронизировано)
internal_message = models.OneToOneField(
Message,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='messenger_sync',
verbose_name="Внутреннее сообщение"
)
# ID сообщения во внешнем мессенджере
external_id = models.CharField(
max_length=200,
verbose_name="ID в мессенджере"
)
# Отправитель/получатель
sender_account = models.ForeignKey(
MessengerAccount,
on_delete=models.SET_NULL,
null=True,
related_name='sent_messages',
verbose_name="Отправитель"
)
recipient_account = models.ForeignKey(
MessengerAccount,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='received_messages',
verbose_name="Получатель"
)
direction = models.CharField(
max_length=10,
choices=DIRECTION_CHOICES,
verbose_name="Направление"
)
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='pending',
verbose_name="Статус"
)
# Содержимое
content = models.TextField(verbose_name="Текст")
# Вложения (JSON с URLs)
attachments = models.JSONField(
default=list,
blank=True,
verbose_name="Вложения"
)
# Временные метки
external_timestamp = models.DateTimeField(
verbose_name="Время в мессенджере"
)
synced_at = models.DateTimeField(
auto_now_add=True,
verbose_name="Синхронизировано"
)
# Дополнительные данные из мессенджера
raw_data = models.JSONField(
default=dict,
blank=True,
verbose_name="Исходные данные"
)
class Meta:
verbose_name = "Сообщение из мессенджера"
verbose_name_plural = "Сообщения из мессенджеров"
unique_together = [('integration', 'external_id')]
indexes = [
models.Index(fields=['integration', 'external_timestamp']),
models.Index(fields=['sender_account', 'external_timestamp']),
models.Index(fields=['status']),
models.Index(fields=['-synced_at']),
]
ordering = ['-external_timestamp']
def __str__(self):
return f"{self.integration.get_messenger_type_display()} - {self.external_id}"

View File

@ -460,22 +460,10 @@ def chat_mark_read(request, pk: int):
def whatsapp_view(request):
"""WhatsApp интеграция"""
from django.shortcuts import render
from .models import MessengerIntegration
try:
integration = MessengerIntegration.objects.get(
messenger_type='whatsapp'
)
integration_status = integration.status if integration.is_enabled else 'inactive'
except MessengerIntegration.DoesNotExist:
integration_status = 'not_configured'
return render(request, 'communications/messengers/whatsapp.html', {
'messenger_name': 'WhatsApp',
'messenger_icon': 'bi-whatsapp',
'messenger_color': '#25D366',
'integration_status': integration_status,
'is_admin': request.user.is_staff or request.user.is_superuser,
'messenger_color': '#25D366'
})
@ -483,22 +471,10 @@ def whatsapp_view(request):
def telegram_view(request):
"""Telegram интеграция"""
from django.shortcuts import render
from .models import MessengerIntegration
try:
integration = MessengerIntegration.objects.get(
messenger_type='telegram'
)
integration_status = integration.status if integration.is_enabled else 'inactive'
except MessengerIntegration.DoesNotExist:
integration_status = 'not_configured'
return render(request, 'communications/messengers/telegram.html', {
'messenger_name': 'Telegram',
'messenger_icon': 'bi-telegram',
'messenger_color': '#0088cc',
'integration_status': integration_status,
'is_admin': request.user.is_staff or request.user.is_superuser,
'messenger_color': '#0088cc'
})
@ -506,20 +482,8 @@ def telegram_view(request):
def wechat_view(request):
"""WeChat интеграция"""
from django.shortcuts import render
from .models import MessengerIntegration
try:
integration = MessengerIntegration.objects.get(
messenger_type='wechat'
)
integration_status = integration.status if integration.is_enabled else 'inactive'
except MessengerIntegration.DoesNotExist:
integration_status = 'not_configured'
return render(request, 'communications/messengers/wechat.html', {
'messenger_name': 'WeChat',
'messenger_icon': 'bi-wechat',
'messenger_color': '#09B83E',
'integration_status': integration_status,
'is_admin': request.user.is_staff or request.user.is_superuser,
'messenger_color': '#09B83E'
})

View File

@ -7,130 +7,73 @@
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/components/page-header.css' %}">
<style>
.messenger-container {
min-height: 70vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.messenger-icon {
font-size: 6rem;
color: {{ messenger_color }};
margin-bottom: 2rem;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.messenger-title {
font-size: 2.5rem;
font-weight: 600;
color: {{ messenger_color }};
margin-bottom: 1rem;
}
.messenger-description {
font-size: 1.2rem;
color: var(--bs-secondary);
max-width: 600px;
margin: 0 auto 2rem;
}
.messenger-actions {
display: flex;
gap: 1rem;
flex-wrap: wrap;
justify-content: center;
}
.messenger-btn {
padding: 0.75rem 2rem;
font-size: 1.1rem;
.messenger-iframe-container {
position: relative;
width: 100%;
height: calc(100vh - 180px);
min-height: 600px;
border: 1px solid var(--bs-border-color);
border-radius: 0.5rem;
transition: all 0.3s ease;
overflow: hidden;
background: #fff;
}
.messenger-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
.messenger-iframe {
width: 100%;
height: 100%;
border: none;
}
.messenger-loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
z-index: 1;
}
.messenger-loading i {
font-size: 3rem;
color: {{ messenger_color }};
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
{% endblock %}
{% block content %}
<div class="container">
<div class="container-fluid px-3">
<div class="row">
<div class="col-12">
{% include "includes/components/page_header.html" with icon=messenger_icon title=messenger_name %}
<div class="card shadow-sm">
<div class="card-body messenger-container">
<i class="{{ messenger_icon }} messenger-icon"></i>
<h2 class="messenger-title">{{ messenger_name }} интеграция</h2>
<p class="messenger-description">
{% if integration_status == 'active' %}
Интеграция активна. Вы можете отправлять и получать сообщения через Telegram.
{% elif integration_status == 'inactive' %}
Интеграция не настроена. Обратитесь к администратору для настройки.
{% else %}
Здесь будет отображаться интеграция с {{ messenger_name }}.
Функционал находится в разработке.
{% endif %}
</p>
<div class="messenger-actions">
<a href="{% url 'communications:chat_list' %}" class="btn btn-outline-secondary messenger-btn">
<i class="bi-arrow-left"></i> Вернуться к чатам
</a>
{% if is_admin %}
<a href="/admin/communications/messengerintegration/" class="btn btn-primary messenger-btn" style="background-color: {{ messenger_color }}; border-color: {{ messenger_color }};">
<i class="bi-gear"></i> Настроить интеграцию
</a>
{% else %}
<button class="btn btn-primary messenger-btn" style="background-color: {{ messenger_color }}; border-color: {{ messenger_color }};" disabled>
<i class="bi-link-45deg"></i> Подключить {{ messenger_name }}
</button>
{% endif %}
</div>
<div class="mt-5">
{% if is_admin %}
<div class="alert alert-success d-inline-block">
<i class="bi-shield-check"></i> У вас есть права администратора
</div>
<div class="mt-3">
<h5>Инструкции для настройки:</h5>
<ol class="text-start" style="max-width: 600px; margin: 0 auto;">
<li>Создайте бота через @BotFather в Telegram</li>
<li>Получите Bot Token</li>
<li>Откройте <a href="/admin/communications/messengerintegration/">админ-панель интеграций</a></li>
<li>Создайте новую интеграцию для Telegram</li>
<li>Укажите Bot Token в поле API ключ</li>
<li>Настройте webhook</li>
<li>Активируйте интеграцию</li>
</ol>
<div class="mt-3">
<a href="/static/communications/MESSENGER_INTEGRATION_GUIDE.md" target="_blank" class="btn btn-sm btn-outline-info">
<i class="bi-book"></i> Полная документация
</a>
</div>
</div>
{% else %}
<div class="alert alert-info d-inline-block">
<i class="bi-info-circle"></i> Для настройки интеграции обратитесь к администратору
</div>
{% endif %}
<div class="card-body p-0">
<div class="messenger-iframe-container">
<div class="messenger-loading">
<i class="bi-arrow-repeat"></i>
<p class="mt-2 text-muted">Загрузка {{ messenger_name }}...</p>
</div>
<iframe
class="messenger-iframe"
src="https://web.telegram.org/"
allow="microphone; camera"
onload="document.querySelector('.messenger-loading').style.display='none'">
</iframe>
</div>
</div>
</div>
<div class="mt-3">
<a href="{% url 'communications:chat_list' %}" class="btn btn-outline-secondary">
<i class="bi-arrow-left"></i> Вернуться к чатам
</a>
</div>
</div>
</div>
</div>

View File

@ -7,130 +7,87 @@
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/components/page-header.css' %}">
<style>
.messenger-container {
min-height: 70vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.messenger-icon {
font-size: 6rem;
color: {{ messenger_color }};
margin-bottom: 2rem;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.messenger-title {
font-size: 2.5rem;
font-weight: 600;
color: {{ messenger_color }};
margin-bottom: 1rem;
}
.messenger-description {
font-size: 1.2rem;
color: var(--bs-secondary);
max-width: 600px;
margin: 0 auto 2rem;
}
.messenger-actions {
display: flex;
gap: 1rem;
flex-wrap: wrap;
justify-content: center;
}
.messenger-btn {
padding: 0.75rem 2rem;
font-size: 1.1rem;
.messenger-iframe-container {
position: relative;
width: 100%;
height: calc(100vh - 180px);
min-height: 600px;
border: 1px solid var(--bs-border-color);
border-radius: 0.5rem;
transition: all 0.3s ease;
overflow: hidden;
background: #fff;
}
.messenger-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
.messenger-iframe {
width: 100%;
height: 100%;
border: none;
}
.messenger-loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
z-index: 1;
}
.messenger-loading i {
font-size: 3rem;
color: {{ messenger_color }};
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.wechat-notice {
padding: 1rem;
background: #fff3cd;
border: 1px solid #ffc107;
border-radius: 0.5rem;
margin-bottom: 1rem;
}
</style>
{% endblock %}
{% block content %}
<div class="container">
<div class="container-fluid px-3">
<div class="row">
<div class="col-12">
{% include "includes/components/page_header.html" with icon=messenger_icon title=messenger_name %}
<div class="wechat-notice">
<i class="bi-info-circle text-warning"></i>
<strong>Внимание:</strong> WeChat не имеет полноценной веб-версии.
Используйте <a href="https://www.wechat.com/en/" target="_blank">официальное приложение</a>.
</div>
<div class="card shadow-sm">
<div class="card-body messenger-container">
<i class="{{ messenger_icon }} messenger-icon"></i>
<h2 class="messenger-title">{{ messenger_name }} интеграция</h2>
<p class="messenger-description">
{% if integration_status == 'active' %}
Интеграция активна. Вы можете отправлять и получать сообщения через WeChat.
{% elif integration_status == 'inactive' %}
Интеграция не настроена. Обратитесь к администратору для настройки.
{% else %}
Здесь будет отображаться интеграция с {{ messenger_name }}.
Функционал находится в разработке.
{% endif %}
</p>
<div class="messenger-actions">
<a href="{% url 'communications:chat_list' %}" class="btn btn-outline-secondary messenger-btn">
<i class="bi-arrow-left"></i> Вернуться к чатам
</a>
{% if is_admin %}
<a href="/admin/communications/messengerintegration/" class="btn btn-primary messenger-btn" style="background-color: {{ messenger_color }}; border-color: {{ messenger_color }};">
<i class="bi-gear"></i> Настроить интеграцию
</a>
{% else %}
<button class="btn btn-primary messenger-btn" style="background-color: {{ messenger_color }}; border-color: {{ messenger_color }};" disabled>
<i class="bi-link-45deg"></i> Подключить {{ messenger_name }}
</button>
{% endif %}
</div>
<div class="mt-5">
{% if is_admin %}
<div class="alert alert-success d-inline-block">
<i class="bi-shield-check"></i> У вас есть права администратора
</div>
<div class="mt-3">
<h5>Инструкции для настройки:</h5>
<ol class="text-start" style="max-width: 600px; margin: 0 auto;">
<li>Зарегистрируйте WeChat Official Account</li>
<li>Получите AppID и AppSecret</li>
<li>Откройте <a href="/admin/communications/messengerintegration/">админ-панель интеграций</a></li>
<li>Создайте новую интеграцию для WeChat</li>
<li>Укажите AppID и AppSecret</li>
<li>Настройте webhook</li>
<li>Активируйте интеграцию</li>
</ol>
<div class="mt-3">
<a href="/static/communications/MESSENGER_INTEGRATION_GUIDE.md" target="_blank" class="btn btn-sm btn-outline-info">
<i class="bi-book"></i> Полная документация
</a>
</div>
</div>
{% else %}
<div class="alert alert-info d-inline-block">
<i class="bi-info-circle"></i> Для настройки интеграции обратитесь к администратору
</div>
{% endif %}
<div class="card-body p-0">
<div class="messenger-iframe-container">
<div class="messenger-loading">
<i class="bi-arrow-repeat"></i>
<p class="mt-2 text-muted">Загрузка {{ messenger_name }}...</p>
</div>
<iframe
class="messenger-iframe"
src="https://www.wechat.com/"
allow="microphone; camera"
onload="document.querySelector('.messenger-loading').style.display='none'">
</iframe>
</div>
</div>
</div>
<div class="mt-3">
<a href="{% url 'communications:chat_list' %}" class="btn btn-outline-secondary">
<i class="bi-arrow-left"></i> Вернуться к чатам
</a>
</div>
</div>
</div>
</div>

View File

@ -7,128 +7,73 @@
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/components/page-header.css' %}">
<style>
.messenger-container {
min-height: 70vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.messenger-icon {
font-size: 6rem;
color: {{ messenger_color }};
margin-bottom: 2rem;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.messenger-title {
font-size: 2.5rem;
font-weight: 600;
color: {{ messenger_color }};
margin-bottom: 1rem;
}
.messenger-description {
font-size: 1.2rem;
color: var(--bs-secondary);
max-width: 600px;
margin: 0 auto 2rem;
}
.messenger-actions {
display: flex;
gap: 1rem;
flex-wrap: wrap;
justify-content: center;
}
.messenger-btn {
padding: 0.75rem 2rem;
font-size: 1.1rem;
.messenger-iframe-container {
position: relative;
width: 100%;
height: calc(100vh - 180px);
min-height: 600px;
border: 1px solid var(--bs-border-color);
border-radius: 0.5rem;
transition: all 0.3s ease;
overflow: hidden;
background: #fff;
}
.messenger-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
.messenger-iframe {
width: 100%;
height: 100%;
border: none;
}
.messenger-loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
z-index: 1;
}
.messenger-loading i {
font-size: 3rem;
color: {{ messenger_color }};
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
{% endblock %}
{% block content %}
<div class="container">
<div class="container-fluid px-3">
<div class="row">
<div class="col-12">
{% include "includes/components/page_header.html" with icon=messenger_icon title=messenger_name %}
<div class="card shadow-sm">
<div class="card-body messenger-container">
<i class="{{ messenger_icon }} messenger-icon"></i>
<h2 class="messenger-title">{{ messenger_name }} интеграция</h2>
<p class="messenger-description">
{% if integration_status == 'active' %}
Интеграция активна. Вы можете отправлять и получать сообщения через WhatsApp.
{% elif integration_status == 'inactive' %}
Интеграция не настроена. Обратитесь к администратору для настройки.
{% else %}
Здесь будет отображаться интеграция с {{ messenger_name }}.
Функционал находится в разработке.
{% endif %}
</p>
<div class="messenger-actions">
<a href="{% url 'communications:chat_list' %}" class="btn btn-outline-secondary messenger-btn">
<i class="bi-arrow-left"></i> Вернуться к чатам
</a>
{% if is_admin %}
<a href="/admin/communications/messengerintegration/" class="btn btn-primary messenger-btn" style="background-color: {{ messenger_color }}; border-color: {{ messenger_color }};">
<i class="bi-gear"></i> Настроить интеграцию
</a>
{% else %}
<button class="btn btn-primary messenger-btn" style="background-color: {{ messenger_color }}; border-color: {{ messenger_color }};" disabled>
<i class="bi-link-45deg"></i> Подключить {{ messenger_name }}
</button>
{% endif %}
</div>
<div class="mt-5">
{% if is_admin %}
<div class="alert alert-success d-inline-block">
<i class="bi-shield-check"></i> У вас есть права администратора
</div>
<div class="mt-3">
<h5>Инструкции для настройки:</h5>
<ol class="text-start" style="max-width: 600px; margin: 0 auto;">
<li>Получите API ключи от WhatsApp Business API</li>
<li>Откройте <a href="/admin/communications/messengerintegration/">админ-панель интеграций</a></li>
<li>Создайте новую интеграцию для WhatsApp</li>
<li>Укажите API ключ и webhook URL</li>
<li>Активируйте интеграцию</li>
</ol>
<div class="mt-3">
<a href="/static/communications/MESSENGER_INTEGRATION_GUIDE.md" target="_blank" class="btn btn-sm btn-outline-info">
<i class="bi-book"></i> Полная документация
</a>
</div>
</div>
{% else %}
<div class="alert alert-info d-inline-block">
<i class="bi-info-circle"></i> Для настройки интеграции обратитесь к администратору
</div>
{% endif %}
<div class="card-body p-0">
<div class="messenger-iframe-container">
<div class="messenger-loading">
<i class="bi-arrow-repeat"></i>
<p class="mt-2 text-muted">Загрузка {{ messenger_name }}...</p>
</div>
<iframe
class="messenger-iframe"
src="https://web.whatsapp.com/"
allow="microphone; camera"
onload="document.querySelector('.messenger-loading').style.display='none'">
</iframe>
</div>
</div>
</div>
<div class="mt-3">
<a href="{% url 'communications:chat_list' %}" class="btn btn-outline-secondary">
<i class="bi-arrow-left"></i> Вернуться к чатам
</a>
</div>
</div>
</div>
</div>