mattermost: автозаполнение бота из Mattermost по токену
Если у бота задан только access-token (без id/username/имени), при сохранении в админке дёргаем GET users/me этим токеном и заполняем user_id, username, display_name автоматически. - MattermostService.identity_for_token(token) — кто владелец токена; - MattermostBotAdmin.save_model подставляет пустые поля, сообщает результат. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from django import forms
|
||||
from django.contrib import admin
|
||||
from django.contrib import admin, messages
|
||||
from unfold.admin import ModelAdmin, TabularInline
|
||||
from unfold.decorators import display
|
||||
from django.utils.html import format_html
|
||||
@@ -78,6 +78,35 @@ class MattermostBotAdmin(ModelAdmin):
|
||||
def caps_display(self, obj):
|
||||
return ', '.join(obj.caps()) or '—'
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
# Задан только токен — подтянуть id/username/имя из Mattermost (GET users/me).
|
||||
if obj.token and (not obj.user_id or not obj.username or not obj.display_name):
|
||||
try:
|
||||
from apps.mattermost_connector.mattermost_service import MattermostService
|
||||
info = MattermostService.identity_for_token(obj.token)
|
||||
if info and info.get('user_id'):
|
||||
obj.user_id = obj.user_id or info['user_id']
|
||||
obj.username = obj.username or info['username']
|
||||
obj.display_name = obj.display_name or info['display_name']
|
||||
self.message_user(
|
||||
request,
|
||||
f'Данные бота получены из Mattermost: @{obj.username} (id={obj.user_id})',
|
||||
level=messages.SUCCESS,
|
||||
)
|
||||
elif info is None:
|
||||
self.message_user(
|
||||
request,
|
||||
'Коннектор Mattermost не настроен — автозаполнение бота пропущено.',
|
||||
level=messages.WARNING,
|
||||
)
|
||||
except Exception as e:
|
||||
self.message_user(
|
||||
request,
|
||||
f'Не удалось получить данные бота из Mattermost (проверьте токен): {e}',
|
||||
level=messages.WARNING,
|
||||
)
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
|
||||
@admin.register(MattermostTeam)
|
||||
class MattermostTeamAdmin(ModelAdmin):
|
||||
|
||||
@@ -85,6 +85,33 @@ class MattermostService:
|
||||
"""Получение пользователя по username"""
|
||||
return self._call(f'GET users/username/{username}', self.driver.users.get_user_by_username, username)
|
||||
|
||||
@staticmethod
|
||||
def identity_for_token(token: str) -> Dict | None:
|
||||
"""Кто владелец токена (GET users/me): id/username/display_name.
|
||||
|
||||
Используется, чтобы автозаполнить карточку бота, когда задан только
|
||||
access-token. Возвращает None, если коннектор не настроен или токен пуст.
|
||||
"""
|
||||
from core.models import ConnectorConfig
|
||||
cfg = ConnectorConfig.objects.filter(connector_type='mattermost', is_enabled=True).first()
|
||||
if not cfg or not cfg.host or not token:
|
||||
return None
|
||||
scheme = 'https' if cfg.use_ssl else 'http'
|
||||
port = cfg.port or (443 if cfg.use_ssl else 80)
|
||||
driver = TypedDriver({'url': cfg.host, 'port': port, 'scheme': scheme, 'timeout': 30})
|
||||
driver.client.token = token
|
||||
me = driver.users.get_user('me')
|
||||
display = (
|
||||
me.get('nickname')
|
||||
or f"{me.get('first_name', '')} {me.get('last_name', '')}".strip()
|
||||
or me.get('username', '')
|
||||
)
|
||||
return {
|
||||
'user_id': me.get('id', ''),
|
||||
'username': me.get('username', ''),
|
||||
'display_name': display,
|
||||
}
|
||||
|
||||
def update_user(self, user_id: str, user_data: Dict) -> Dict:
|
||||
"""Обновление данных пользователя через PATCH"""
|
||||
return self._call(f'PATCH users/{user_id}', self.driver.users.patch_user, user_id, log_data=user_data, **user_data)
|
||||
|
||||
Reference in New Issue
Block a user