from __future__ import annotations from telegram import Update from telegram.ext import ContextTypes from sqlalchemy import desc from app.core.db import db_session from app.repositories.admin_repo import AdminRepository from app.repositories.candidate_repo import CandidateRepository from app.models.candidate import Candidate from app.utils.common import csv_to_list async def add_admin_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): """Команда /addadmin — добавить нового администратора (только для админов).""" with db_session() as s: repo = AdminRepository(s) if not repo.is_admin(update.effective_user.id): await update.message.reply_text("Недостаточно прав.") return args = context.args or [] if not args: await update.message.reply_text("Формат: /addadmin 123456789") return try: tid = int(args[0]) except ValueError: await update.message.reply_text("Неверный telegram_id.") return from app.models.admin import Admin if s.query(Admin).filter(Admin.telegram_id == tid).first(): await update.message.reply_text("Этот администратор уже добавлен.") return s.add(Admin(telegram_id=tid)) s.commit() await update.message.reply_text(f"Администратор {tid} добавлен.") async def list_candidates_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): """Команда /candidates — показать последние анкеты (только для админов).""" with db_session() as s: admin_repo = AdminRepository(s) if not admin_repo.is_admin(update.effective_user.id): await update.message.reply_text("Недостаточно прав.") return rows = s.query(Candidate).order_by(desc(Candidate.created_at)).limit(30).all() if not rows: await update.message.reply_text("Кандидатов пока нет.") return out = [] for c in rows: out.append( f"#{c.id} {c.full_name or '—'} | {c.city or '—'} | цель: {c.goal or '—'} | @{c.username or ''}" ) await update.message.reply_text("Последние анкеты:\n" + "\n".join(out)) async def verify_candidate_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): """Команда /verify — пометить анкету как проверенную (только для админов).""" with db_session() as s: admin_repo = AdminRepository(s) if not admin_repo.is_admin(update.effective_user.id): await update.message.reply_text("Недостаточно прав.") return args = context.args or [] if not args: await update.message.reply_text("Формат: /verify 12") return try: cid = int(args[0]) except ValueError: await update.message.reply_text("Укажи числовой id анкеты.") return c = s.get(Candidate, cid) if not c: await update.message.reply_text("Анкета не найдена.") return c.is_verified = True s.commit() await update.message.reply_text(f"Анкета #{cid} помечена как проверенная.") async def view_candidate_handler(update, context): """Команда /view — показать карточку анкеты с фото (для админов).""" with db_session() as s: admin_repo = AdminRepository(s) if not admin_repo.is_admin(update.effective_user.id): await update.message.reply_text("Недостаточно прав.") return args = context.args or [] if not args: await update.message.reply_text("Формат: /view 12") return try: cid = int(args[0]) except ValueError: await update.message.reply_text("Укажи числовой id анкеты.") return c = s.get(Candidate, cid) if not c: await update.message.reply_text("Анкета не найдена.") return # Текстовая карточка caption = ( f"#{c.id} {c.full_name or '—'} @{c.username or ''}\n" f"Город: {c.city or '—'} | Цель: {c.goal or '—'}\n" f"Статус: {'✅ проверена' if c.is_verified else '⏳ на проверке'} | Активна: {'да' if c.is_active else 'нет'}" ) chat_id = update.effective_chat.id # Аватар (если есть) if c.avatar_file_id: await context.bot.send_photo(chat_id=chat_id, photo=c.avatar_file_id, caption=caption) else: await context.bot.send_message(chat_id=chat_id, text=caption + "\n(аватар отсутствует)") # Галерея (если есть) gallery_ids = csv_to_list(c.gallery_file_ids) if gallery_ids: # Telegram принимает до 10 media за раз chunk = [] for fid in gallery_ids: chunk.append(InputMediaPhoto(media=fid)) if len(chunk) == 10: await context.bot.send_media_group(chat_id=chat_id, media=chunk) chunk = [] if chunk: await context.bot.send_media_group(chat_id=chat_id, media=chunk)