176 lines
7.5 KiB
Python
176 lines
7.5 KiB
Python
import logging
|
||
from typing import TYPE_CHECKING
|
||
|
||
from aiogram.types import InlineKeyboardButton
|
||
|
||
from src import domain, dto
|
||
|
||
if TYPE_CHECKING:
|
||
from .. import Usecase
|
||
|
||
log = logging.getLogger(__name__)
|
||
|
||
|
||
async def tg_add_project(self: 'Usecase', input: dto.ConnectProjectInput) -> dto.ProjectOutput | None:
|
||
permissions = input.bot_permissions
|
||
|
||
if not permissions.is_admin:
|
||
log.warning(f'Bot is not admin in channel {input.telegram_id}. Attempted by user {input.user_telegram_id}')
|
||
await self.telegram_bot.send_message(
|
||
f'⚠️ Бот был добавлен в канал "{input.title}", но не является админом.\n\n'
|
||
'Пожалуйста, сделайте бота администратором канала.',
|
||
input.user_telegram_id,
|
||
)
|
||
raise domain.ChannelNoAdminRights()
|
||
|
||
missing_permissions = []
|
||
if not permissions.can_invite_users:
|
||
missing_permissions.append('Создание инвайт-ссылок')
|
||
if not permissions.can_restrict_members:
|
||
missing_permissions.append('Управление пользователями (видеть вступления)')
|
||
|
||
if missing_permissions:
|
||
log.warning(
|
||
f'Bot lacks required permissions in channel {input.telegram_id}: {missing_permissions}. '
|
||
f'Attempted by user {input.user_telegram_id}'
|
||
)
|
||
permissions_text = '\n'.join(f'• {p}' for p in missing_permissions)
|
||
await self.telegram_bot.send_message(
|
||
f'⚠️ Бот был добавлен в канал "{input.title}", но не имеет необходимых прав.\n\n'
|
||
f'Отсутствующие права:\n{permissions_text}\n\n'
|
||
'Пожалуйста, предоставьте эти права боту в настройках канала.',
|
||
input.user_telegram_id,
|
||
)
|
||
raise domain.ChannelNoAdminRights()
|
||
|
||
user = await self.database.get_user(telegram_id=input.user_telegram_id)
|
||
if not user:
|
||
log.warning(f'User {input.user_telegram_id} not found when trying to connect channel {input.telegram_id}')
|
||
await self.telegram_bot.send_message(
|
||
f'⚠️ Канал "{input.title}" не может быть подключен.\n\n'
|
||
'Вы должны сначала авторизоваться в веб-панели перед подключением каналов.',
|
||
input.user_telegram_id,
|
||
)
|
||
raise domain.UserNotFound()
|
||
if user.telegram_user is None:
|
||
log.warning('User %s missing telegram profile when connecting channel', user.id)
|
||
await self.telegram_bot.send_message(
|
||
'⚠️ Произошла ошибка при обработке вашего профиля. Пожалуйста, повторите авторизацию.',
|
||
input.user_telegram_id,
|
||
)
|
||
raise domain.UserNotFound()
|
||
|
||
if user.telegram_user is None:
|
||
raise domain.UserNotFound(user.id)
|
||
|
||
telegram_user = user.telegram_user
|
||
|
||
memberships = await self.database.get_user_workspaces(user.id)
|
||
workspaces: list[domain.Workspace] = []
|
||
for membership in memberships:
|
||
workspace: domain.Workspace | None = membership.workspace
|
||
if not workspace:
|
||
workspace = await self.database.get_workspace(membership.workspace_id)
|
||
|
||
if workspace:
|
||
workspaces.append(workspace)
|
||
|
||
if not workspaces:
|
||
workspace = await self.get_or_create_personal_workspace(user)
|
||
workspaces = [workspace]
|
||
|
||
if len(workspaces) == 1:
|
||
workspace = workspaces[0]
|
||
|
||
channel = await self.database.get_channel(telegram_id=input.telegram_id)
|
||
if channel:
|
||
channel.title = input.title
|
||
if input.username is not None:
|
||
channel.username = input.username
|
||
await self.database.update_channel(channel)
|
||
else:
|
||
if input.username is None:
|
||
log.warning('Cannot create channel %s without username', input.telegram_id)
|
||
await self.telegram_bot.send_message(
|
||
f'⚠️ Канал "{input.title}" не может быть подключен.\n\nУ канала отсутствует публичный username.',
|
||
input.user_telegram_id,
|
||
)
|
||
return None
|
||
|
||
channel = domain.Channel(
|
||
telegram_id=input.telegram_id,
|
||
title=input.title,
|
||
username=input.username,
|
||
)
|
||
await self.database.create_channel(channel)
|
||
|
||
project = await self.database.get_project(workspace.id, channel_id=channel.id)
|
||
if project:
|
||
project.status = domain.ProjectStatus.ACTIVE
|
||
await self.database.update_project(project)
|
||
else:
|
||
project = domain.Project(
|
||
workspace_id=workspace.id,
|
||
channel_id=channel.id,
|
||
status=domain.ProjectStatus.ACTIVE,
|
||
)
|
||
await self.database.create_project(project)
|
||
|
||
log.info(
|
||
'Project for channel %s connected/updated successfully in workspace %s by user %s',
|
||
input.telegram_id,
|
||
workspace.id,
|
||
input.user_telegram_id,
|
||
)
|
||
|
||
await self.telegram_bot.send_message(
|
||
f'✅ Канал "{input.title}" добавлен в рабочее пространство "{workspace.name}".', input.user_telegram_id
|
||
)
|
||
|
||
return dto.ProjectOutput(
|
||
id=project.id,
|
||
telegram_id=channel.telegram_id,
|
||
title=channel.title,
|
||
username=channel.username,
|
||
status=project.status,
|
||
purchase_invite_type_default=project.purchase_invite_type_default,
|
||
)
|
||
|
||
# Если >1 workspace - создаем/обновляем канал и отправляем уведомление
|
||
channel = await self.database.get_channel(telegram_id=input.telegram_id)
|
||
if channel:
|
||
channel.title = input.title
|
||
if input.username is not None:
|
||
channel.username = input.username
|
||
await self.database.update_channel(channel)
|
||
else:
|
||
if input.username is None:
|
||
log.warning('Cannot create channel %s without username', input.telegram_id)
|
||
await self.telegram_bot.send_message(
|
||
f'⚠️ Канал "{input.title}" не может быть подключен.\n\nУ канала отсутствует публичный username.',
|
||
input.user_telegram_id,
|
||
)
|
||
return None
|
||
|
||
channel = domain.Channel(
|
||
telegram_id=input.telegram_id,
|
||
title=input.title,
|
||
username=input.username,
|
||
)
|
||
await self.database.create_channel(channel)
|
||
|
||
# Callback будет обработан Golang ботом который покажет экран выбора workspace
|
||
buttons = [[InlineKeyboardButton(text='Выбрать workspace', callback_data=f'pending_channel:{channel.id}')]]
|
||
|
||
await self.telegram_bot.send_message_with_inline_keyboard(
|
||
f'Бот добавлен в канал "{input.title}".\n\n'
|
||
f'У вас {len(workspaces)} рабочих пространств. '
|
||
'Нажмите кнопку ниже чтобы выбрать, где создать проект.',
|
||
telegram_user.telegram_id,
|
||
buttons,
|
||
)
|
||
|
||
log.info('Pending channel notification sent to user %s for channel %s', telegram_user.telegram_id, channel.id)
|
||
|
||
return None
|