Some checks reported errors
continuous-integration/drone/push Build encountered an error
141 lines
5.6 KiB
Python
141 lines
5.6 KiB
Python
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 <telegram_id> — добавить нового администратора (только для админов)."""
|
||
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 <id> — пометить анкету как проверенную (только для админов)."""
|
||
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 <id> — показать карточку анкеты с фото (для админов)."""
|
||
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) |