This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Использование (из корня проекта):
|
||||
# bash tools/ops/copy_databases.sh <source_db> <target_db> <username>
|
||||
# Пример:
|
||||
# bash tools/ops/copy_databases.sh old_db new_db appuser
|
||||
|
||||
set -e # Завершать выполнение при любой ошибке
|
||||
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo "Использование: $0 <исходная_база> <целевая_база> <имя_пользователя>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE_DB="$1"
|
||||
TARGET_DB="$2"
|
||||
DB_USER="$3"
|
||||
BACKUP_DIR="."
|
||||
|
||||
# Функция для запроса пароля от MariaDB один раз
|
||||
read_mysql_password() {
|
||||
if [ -z "$MYSQL_PWD" ]; then
|
||||
read -s -p "Введите пароль MariaDB для пользователя root: " MYSQL_PWD
|
||||
echo
|
||||
export MYSQL_PWD
|
||||
fi
|
||||
}
|
||||
|
||||
# Функция проверки существования базы данных
|
||||
db_exists() {
|
||||
local db_name="$1"
|
||||
if mysql -u root -e "SHOW DATABASES LIKE '$db_name';" | grep -q "^$db_name$"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Функция резервного копирования базы
|
||||
backup_db() {
|
||||
local db_name="$1"
|
||||
local backup_file="${BACKUP_DIR}/${db_name}.backup.sql"
|
||||
echo "Создаётся резервная копия базы '$db_name' в файл '$backup_file'..."
|
||||
mysqldump -u root \
|
||||
--routines \
|
||||
--triggers \
|
||||
--events \
|
||||
--single-transaction \
|
||||
"$db_name" > "$backup_file"
|
||||
echo "Резервная копия '$db_name' успешно создана."
|
||||
}
|
||||
|
||||
# === НАЧАЛО ОСНОВНОГО СЦЕНАРИЯ ===
|
||||
|
||||
read_mysql_password
|
||||
|
||||
echo "Проверка существования исходной базы '$SOURCE_DB'..."
|
||||
if ! db_exists "$SOURCE_DB"; then
|
||||
echo "Ошибка: исходная база данных '$SOURCE_DB' не существует."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Резервное копирование исходной базы (всегда)
|
||||
backup_db "$SOURCE_DB"
|
||||
|
||||
# Проверка существования целевой базы
|
||||
if db_exists "$TARGET_DB"; then
|
||||
echo "Целевая база '$TARGET_DB' уже существует."
|
||||
backup_db "$TARGET_DB"
|
||||
echo "Удаление существующей базы '$TARGET_DB'..."
|
||||
mysql -u root -e "DROP DATABASE \`$TARGET_DB\`;"
|
||||
else
|
||||
echo "Целевая база '$TARGET_DB' не существует — будет создана."
|
||||
fi
|
||||
|
||||
# Создание новой целевой базы
|
||||
echo "Создание новой базы '$TARGET_DB'..."
|
||||
mysql -u root -e "CREATE DATABASE \`$TARGET_DB\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
||||
|
||||
# Создание временного дампа без указания базы (без CREATE DATABASE и USE)
|
||||
TEMP_DUMP=$(mktemp)
|
||||
echo "Создание временного дампа из '$SOURCE_DB'..."
|
||||
mysqldump -u root \
|
||||
--routines \
|
||||
--triggers \
|
||||
--events \
|
||||
--single-transaction \
|
||||
--no-create-db \
|
||||
"$SOURCE_DB" > "$TEMP_DUMP"
|
||||
|
||||
# Восстановление в целевую базу
|
||||
echo "Восстановление данных в '$TARGET_DB'..."
|
||||
mysql -u root "$TARGET_DB" < "$TEMP_DUMP"
|
||||
|
||||
# Удаление временного файла
|
||||
rm -f "$TEMP_DUMP"
|
||||
|
||||
# Настройка прав пользователя
|
||||
echo "Настройка прав для пользователя '$DB_USER'@'%' на базу '$TARGET_DB'..."
|
||||
mysql -u root -e "CREATE USER IF NOT EXISTS \`$DB_USER\`@'%';"
|
||||
mysql -u root -e "GRANT ALL PRIVILEGES ON \`$TARGET_DB\`.* TO \`$DB_USER\`@'%';"
|
||||
mysql -u root -e "FLUSH PRIVILEGES;"
|
||||
|
||||
echo "✅ Копирование завершено успешно!"
|
||||
echo "Исходная база: $SOURCE_DB → Целевая база: $TARGET_DB"
|
||||
echo "Пользователь: $DB_USER@% имеет полные права на целевую базу."
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Генерация случайного hex-ключа для SECRET_KEY или WEBHOOK_SECRET.
|
||||
|
||||
Запуск из корня проекта:
|
||||
python tools/ops/genkey.py
|
||||
"""
|
||||
import secrets
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(secrets.token_hex(32))
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Ручная регистрация Telegram webhook через internal_relay (с secret_token).
|
||||
|
||||
Запуск из корня проекта:
|
||||
./venv/bin/python tools/ops/register_tg_webhook.py
|
||||
|
||||
Печатает полный ответ setWebhook — по нему видно, принял ли Telegram секрет.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
_PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
if _PROJECT_ROOT not in sys.path:
|
||||
sys.path.insert(0, _PROJECT_ROOT)
|
||||
|
||||
from dotenv import load_dotenv
|
||||
import requests
|
||||
|
||||
load_dotenv(os.path.join(_PROJECT_ROOT, ".env"))
|
||||
load_dotenv()
|
||||
|
||||
from telegram_relay import bot_api_method_url, get_relay_url
|
||||
|
||||
TOKEN = os.getenv("RESPONDER_BOT_TOKEN")
|
||||
WEBHOOK_URL = os.getenv("WEBHOOK_URL")
|
||||
WEBHOOK_SECRET = (os.getenv("WEBHOOK_SECRET") or "").strip().strip('"').strip("'")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if not TOKEN:
|
||||
print("ERROR: RESPONDER_BOT_TOKEN не задан")
|
||||
return 1
|
||||
if not WEBHOOK_URL:
|
||||
print("ERROR: WEBHOOK_URL не задан")
|
||||
return 1
|
||||
if not WEBHOOK_SECRET:
|
||||
print("ERROR: WEBHOOK_SECRET не задан")
|
||||
return 1
|
||||
|
||||
api_url = bot_api_method_url(TOKEN, "setWebhook")
|
||||
form = {
|
||||
"url": WEBHOOK_URL,
|
||||
"secret_token": WEBHOOK_SECRET,
|
||||
"max_connections": "40",
|
||||
# Иначе Telegram может сохранить старый список без callback_query
|
||||
"allowed_updates": json.dumps([
|
||||
"message",
|
||||
"edited_message",
|
||||
"callback_query",
|
||||
]),
|
||||
}
|
||||
print(f"RELAY_URL = {get_relay_url()}")
|
||||
print(f"WEBHOOK_URL = {WEBHOOK_URL}")
|
||||
print(f"secret_len = {len(WEBHOOK_SECRET)}")
|
||||
print(f"POST = {api_url.replace(TOKEN, '<TOKEN>')}")
|
||||
print(f"form keys = {list(form.keys())}")
|
||||
|
||||
resp = requests.post(api_url, data=form, timeout=60)
|
||||
print(f"HTTP status = {resp.status_code}")
|
||||
try:
|
||||
data = resp.json()
|
||||
print("JSON response:")
|
||||
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||||
except Exception:
|
||||
print("Raw response:")
|
||||
print(resp.text[:1000])
|
||||
return 1
|
||||
|
||||
if not data.get("ok"):
|
||||
print("FAILED: Telegram/relay вернул ok=false")
|
||||
return 1
|
||||
|
||||
print("OK: setWebhook принят. Нажмите «Подписка» / отправьте /start боту.")
|
||||
print("В логе бота не должно быть «Секретный токен отсутствует».")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user