Правки админки: инлайн-кнопки, отмена рассылки, FAQ в меню, вакансии в БД

- Отмена в «Заявке»/«Карьере» возвращает меню с кнопкой «Админка» для админов.
- Рассылка: инлайн-кнопки «Отправить»/«Отмена» в предпросмотре.
- Управление админами — инлайн-кнопки «Добавить»/«Удалить» (без текстовых команд),
  выбор удаляемого админа кнопкой.
- Быстрые ответы из админки показываются в «Частые вопросы» инлайн-кнопками.
- Вакансии «Карьеры» перенесены в БД (vacancy_options): направления игроков и
  должности сотрудников редактируются из админки (раздел «Вакансии»), а в опросе
  показываются инлайн-кнопками из БД.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kenik
2026-06-24 19:36:53 +03:00
parent 755e364d42
commit 564581decf
8 changed files with 247 additions and 50 deletions
+43
View File
@@ -123,6 +123,24 @@ class DatabaseManager:
except sqlite3.OperationalError:
pass
# Table for vacancy options (направления игроков и должности сотрудников)
cursor.execute("""
CREATE TABLE IF NOT EXISTS vacancy_options (
id INTEGER PRIMARY KEY AUTOINCREMENT,
track TEXT NOT NULL, -- 'player' | 'worker'
label TEXT NOT NULL,
is_active INTEGER DEFAULT 1
)
""")
cursor.execute("SELECT COUNT(*) FROM vacancy_options")
if cursor.fetchone()[0] == 0:
seed = [
("player", "Counter-Strike 2 🔫"), ("player", "Dota 2 🎮"), ("player", "World of Tanks 🛡️"),
("worker", "SMM / контент"), ("worker", "Монтажёр / дизайнер"),
("worker", "Менеджер"), ("worker", "Разработчик"),
]
cursor.executemany("INSERT INTO vacancy_options (track, label) VALUES (?, ?)", seed)
# Table for runtime-added admins (добавляются супер-админом из бота)
cursor.execute("""
CREATE TABLE IF NOT EXISTS admins (
@@ -434,6 +452,31 @@ class DatabaseManager:
)
conn.commit()
# --- Вакансии (направления игроков / должности сотрудников) ---
def get_vacancy_options(self, track: str) -> list:
"""Активные опции для трека ('player'|'worker') как список (id, label)."""
with self._get_connection() as conn:
cursor = conn.cursor()
cursor.execute(
"SELECT id, label FROM vacancy_options WHERE track = ? AND is_active = 1 ORDER BY id",
(track,)
)
return cursor.fetchall()
def add_vacancy_option(self, track: str, label: str) -> int:
with self._get_connection() as conn:
cursor = conn.cursor()
cursor.execute("INSERT INTO vacancy_options (track, label) VALUES (?, ?)", (track, label.strip()))
conn.commit()
return cursor.lastrowid
def delete_vacancy_option(self, option_id: int) -> bool:
with self._get_connection() as conn:
cursor = conn.cursor()
cursor.execute("UPDATE vacancy_options SET is_active = 0 WHERE id = ?", (option_id,))
conn.commit()
return cursor.rowcount > 0
# --- Администраторы (добавленные в рантайме супер-админом) ---
def add_admin(self, user_id: int) -> bool:
with self._get_connection() as conn: