/
AAAAAAAAAA
/
Telegram1
Обзор
Документация
Войти
/
AAAAAAAAAA
/
Telegram1
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
check_database.py
876 строк
35 KB
AAAAAAAAAA
upload files
05 фев 2026, 15:43
Верифицирован
05 фев 2026, 15:43
21e7500
Код
Авторство
О чём код?
import os import sqlite3 import csv import json from datetime import datetime, timedelta from dotenv import load_dotenv # Загружаем конфигурацию load_dotenv() DATABASE_PATH = os.getenv("DATABASE_PATH", "webinar_registrations.db") def get_db_connection(): """Создает подключение к базе данных""" return sqlite3.connect(DATABASE_PATH, check_same_thread=False) def print_section(title): """Печатает разделитель секции""" print("\n" + "="*60) print(f"📊 {title}") print("="*60) def print_info(message): """Печатает информационное сообщение""" print(f"ℹ️ {message}") def print_success(message): """Печатает сообщение об успехе""" print(f"✅ {message}") def print_warning(message): """Печатает предупреждение""" print(f"⚠️ {message}") def print_error(message): """Печатает сообщение об ошибке""" print(f"❌ {message}") def test_database_connection(): """Тест подключения к базе""" try: print_section("ПОДКЛЮЧЕНИЕ К БАЗЕ ДАННЫХ") if os.path.exists(DATABASE_PATH): size = os.path.getsize(DATABASE_PATH) size_mb = size / (1024 * 1024) print_info(f"Файл базы: {DATABASE_PATH}") print_info(f"Размер файла: {size:,} байт ({size_mb:.2f} MB)") # Проверяем версию SQLite conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT sqlite_version()") sqlite_version = cursor.fetchone()[0] print_info(f"Версия SQLite: {sqlite_version}") # Проверяем кодировку cursor.execute("PRAGMA encoding") encoding = cursor.fetchone()[0] print_info(f"Кодировка базы: {encoding}") conn.close() print_success("Подключение к базе успешно") return True else: print_error("Файл базы данных не найден!") return False except Exception as e: print_error(f"Ошибка подключения: {e}") return False def list_all_tables(): """Показывает все таблицы в базе""" try: print_section("ВСЕ ТАБЛИЦЫ В БАЗЕ ДАННЫХ") conn = get_db_connection() cursor = conn.cursor() # Получаем все таблицы cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name") tables = cursor.fetchall() print_info(f"Найдено таблиц: {len(tables)}") print("\n№ | Таблица | Записей | Столбцов") print("-" * 50) table_stats = [] for idx, (table_name,) in enumerate(tables, 1): # Количество записей try: cursor.execute(f"SELECT COUNT(*) FROM {table_name}") row_count = cursor.fetchone()[0] except: row_count = "N/A" # Количество столбцов try: cursor.execute(f"PRAGMA table_info({table_name})") columns = cursor.fetchall() col_count = len(columns) except: col_count = "N/A" table_stats.append((table_name, row_count, col_count)) print(f"{idx:2} | {table_name:<20} | {row_count:>7} | {col_count:>8}") conn.close() return table_stats except Exception as e: print_error(f"Ошибка получения списка таблиц: {e}") return [] def check_table_structure(table_name): """Проверяет структуру таблицы""" try: conn = get_db_connection() cursor = conn.cursor() print(f"\n📋 Структура таблицы '{table_name}':") print(" ID | Имя колонки | Тип данных | NULL? | PK?") print(" " + "-" * 60) cursor.execute(f"PRAGMA table_info({table_name})") columns = cursor.fetchall() for col in columns: col_id, col_name, col_type, not_null, default_val, pk = col print(f" {col_id:2} | {col_name:<20} | {col_type:<12} | {bool(not_null)} | {bool(pk)}") conn.close() return columns except Exception as e: print_error(f"Ошибка проверки структуры таблицы {table_name}: {e}") return [] def check_registrations_table(): """Проверяем таблицу регистраций""" try: print_section("ТАБЛИЦА РЕГИСТРАЦИЙ (registrations)") conn = get_db_connection() cursor = conn.cursor() # Проверяем наличие таблицы cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='registrations'") if not cursor.fetchone(): print_error("Таблица 'registrations' не найдена!") conn.close() return # Количество записей cursor.execute('SELECT COUNT(*) FROM registrations') total = cursor.fetchone()[0] print_info(f"Всего записей: {total}") if total == 0: print_warning("Таблица пуста") conn.close() return # Уникальные пользователи cursor.execute('SELECT COUNT(DISTINCT user_id) FROM registrations') unique_users = cursor.fetchone()[0] print_info(f"Уникальных пользователей: {unique_users}") # Последние записи cursor.execute(''' SELECT user_id, first_name, phone_number, registered_at FROM registrations ORDER BY registered_at DESC LIMIT 10 ''') recent_users = cursor.fetchall() print("\n📅 Последние 10 записей:") print(" Имя | Телефон | User ID | Дата регистрации") print(" " + "-" * 60) for user in recent_users: reg_date = user[3].split('.')[0] if user[3] and '.' in user[3] else user[3] print(f" {user[1]:<15} | {user[2]:<12} | {user[0]:<9} | {reg_date}") # Диапазон дат cursor.execute('SELECT MIN(registered_at), MAX(registered_at) FROM registrations') dates = cursor.fetchone() print(f"\n📅 Первая регистрация: {dates[0]}") print(f"📅 Последняя регистрация: {dates[1]}") # Статистика по дням cursor.execute(''' SELECT date(registered_at) as reg_date, COUNT(*) as count FROM registrations WHERE registered_at IS NOT NULL GROUP BY date(registered_at) ORDER BY reg_date DESC LIMIT 7 ''') daily_stats = cursor.fetchall() if daily_stats: print("\n📈 Статистика за последние 7 дней:") total_week = 0 for date_str, count in daily_stats: print(f" {date_str}: {count} регистраций") total_week += count avg_per_day = total_week / len(daily_stats) print(f"\n📊 Среднее в день: {avg_per_day:.1f} регистраций") conn.close() except Exception as e: print_error(f"Ошибка проверки таблицы регистраций: {e}") def check_user_actions_table(): """Проверяем таблицу действий пользователей""" try: print_section("ТАБЛИЦА ДЕЙСТВИЙ ПОЛЬЗОВАТЕЛЕЙ (user_actions)") conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='user_actions'") if not cursor.fetchone(): print_error("Таблица 'user_actions' не найдена!") conn.close() return # Общая статистика cursor.execute('SELECT COUNT(*) FROM user_actions') total = cursor.fetchone()[0] print_info(f"Всего действий: {total}") if total == 0: print_warning("Таблица пуста") conn.close() return # Статистика по типам действий cursor.execute(''' SELECT action_type, COUNT(*) as count FROM user_actions GROUP BY action_type ORDER BY count DESC ''') action_stats = cursor.fetchall() print("\n📊 Статистика по типам действий:") for action_type, count in action_stats: print(f" {action_type:<30} : {count:>5}") # Активные пользователи cursor.execute(''' SELECT first_name, COUNT(*) as action_count FROM user_actions WHERE first_name IS NOT NULL GROUP BY user_id ORDER BY action_count DESC LIMIT 10 ''') active_users = cursor.fetchall() if active_users: print("\n🏆 Самые активные пользователи:") for name, count in active_users: print(f" {name:<20} : {count:>3} действий") # Последние действия cursor.execute(''' SELECT first_name, action_type, timestamp FROM user_actions WHERE first_name IS NOT NULL ORDER BY timestamp DESC LIMIT 10 ''') recent_actions = cursor.fetchall() if recent_actions: print("\n🕒 Последние действия:") for name, action, time in recent_actions: time_str = time.split('.')[0] if time and '.' in time else time print(f" {name:<15} - {action:<20} - {time_str}") conn.close() except Exception as e: print_error(f"Ошибка проверки таблицы действий: {e}") def check_broadcasts_table(): """Проверяем таблицу рассылок""" try: print_section("ТАБЛИЦА РАССЫЛОК (broadcasts)") conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='broadcasts'") if not cursor.fetchone(): print_error("Таблица 'broadcasts' не найдена!") conn.close() return # Общая статистика cursor.execute('SELECT COUNT(*) FROM broadcasts') total = cursor.fetchone()[0] print_info(f"Всего рассылок: {total}") if total == 0: print_warning("Таблица пуста") conn.close() return # Статистика по статусам cursor.execute('SELECT status, COUNT(*) FROM broadcasts GROUP BY status') status_stats = cursor.fetchall() print("\n📊 Статистика по статусам:") for status, count in status_stats: print(f" {status:<15} : {count:>3}") # Успешность рассылок cursor.execute('SELECT SUM(success_count), SUM(fail_count) FROM broadcasts WHERE status="completed"') sent_stats = cursor.fetchone() total_sent = sent_stats[0] or 0 if sent_stats[0] is not None else 0 total_failed = sent_stats[1] or 0 if sent_stats[1] is not None else 0 total_attempts = total_sent + total_failed if total_attempts > 0: success_rate = (total_sent / total_attempts) * 100 print(f"\n📈 Успешность рассылок:") print(f" Отправлено успешно: {total_sent}") print(f" Не отправлено: {total_failed}") print(f" Процент успеха: {success_rate:.1f}%") # Последние рассылки cursor.execute(''' SELECT id, broadcast_type, recipients_count, success_count, status, started_at FROM broadcasts ORDER BY started_at DESC LIMIT 5 ''') recent_broadcasts = cursor.fetchall() if recent_broadcasts: print("\n🔄 Последние рассылки:") for b_id, b_type, recipients, success, status, started in recent_broadcasts: started_str = started.split('.')[0] if started and '.' in started else started print(f" #{b_id} | {b_type:<25} | {recipients:>3} получателей | {success:>3} успешно | {status:<10} | {started_str}") conn.close() except Exception as e: print_error(f"Ошибка проверки таблицы рассылок: {e}") def check_amocrm_tables(): """Проверяем таблицы amoCRM""" try: print_section("ТАБЛИЦЫ AMOCRM") conn = get_db_connection() cursor = conn.cursor() # Проверяем все таблицы amoCRM amocrm_tables = [ 'amocrm_webhook_details', 'amocrm_leads', 'amocrm_contacts', 'amocrm_bot_notifications', 'amocrm_events' ] for table_name in amocrm_tables: cursor.execute(f"SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}'") if cursor.fetchone(): cursor.execute(f"SELECT COUNT(*) FROM {table_name}") count = cursor.fetchone()[0] print_success(f"{table_name:<30} : {count:>5} записей") else: print_warning(f"{table_name:<30} : НЕ НАЙДЕНА") # Детальная проверка вебхуков cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='amocrm_webhook_details'") if cursor.fetchone(): print(f"\n📥 Детализация вебхуков amoCRM:") # Статистика по событиям cursor.execute(''' SELECT event_type, COUNT(*) as count FROM amocrm_webhook_details GROUP BY event_type ORDER BY count DESC ''') event_stats = cursor.fetchall() for event_type, count in event_stats[:10]: # Показываем топ-10 print(f" {event_type:<40} : {count:>5}") # Последние вебхуки cursor.execute(''' SELECT event_type, account_subdomain, created_at FROM amocrm_webhook_details ORDER BY created_at DESC LIMIT 5 ''') recent_webhooks = cursor.fetchall() if recent_webhooks: print("\n🕒 Последние вебхуки:") for event, account, created in recent_webhooks: created_str = created.split('.')[0] if created and '.' in created else created print(f" {event:<30} | {account:<15} | {created_str}") # Проверка уведомлений cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='amocrm_bot_notifications'") if cursor.fetchone(): print(f"\n🔔 Статус уведомлений для бота:") cursor.execute(''' SELECT status, COUNT(*) as count FROM amocrm_bot_notifications GROUP BY status ''') notification_stats = cursor.fetchall() for status, count in notification_stats: print(f" {status:<15} : {count:>5}") conn.close() except Exception as e: print_error(f"Ошибка проверки таблиц amoCRM: {e}") def check_system_logs(): """Проверяем системные логи""" try: print_section("СИСТЕМНЫЕ ЛОГИ (system_logs)") conn = get_db_connection() cursor = conn.cursor() cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='system_logs'") if not cursor.fetchone(): print_error("Таблица 'system_logs' не найдена!") conn.close() return # Общая статистика cursor.execute('SELECT COUNT(*) FROM system_logs') total = cursor.fetchone()[0] print_info(f"Всего логов: {total}") if total == 0: print_warning("Таблица пуста") conn.close() return # Статистика по уровням логирования cursor.execute(''' SELECT log_level, COUNT(*) as count FROM system_logs GROUP BY log_level ORDER BY count DESC ''') level_stats = cursor.fetchall() print("\n📊 Распределение по уровням:") for level, count in level_stats: print(f" {level:<10} : {count:>5}") # Последние ошибки cursor.execute(''' SELECT log_level, message, timestamp FROM system_logs WHERE log_level = 'ERROR' ORDER BY timestamp DESC LIMIT 5 ''') recent_errors = cursor.fetchall() if recent_errors: print("\n❌ Последние ошибки:") for level, message, time in recent_errors: time_str = time.split('.')[0] if time and '.' in time else time print(f" [{time_str}] {message[:100]}...") # Последние логи cursor.execute(''' SELECT log_level, message, timestamp FROM system_logs ORDER BY timestamp DESC LIMIT 10 ''') recent_logs = cursor.fetchall() if recent_logs: print("\n🕒 Последние логи:") for level, message, time in recent_logs: time_str = time.split('.')[0] if time and '.' in time else time msg_preview = message[:80] + "..." if len(message) > 80 else message print(f" [{time_str}] [{level}] {msg_preview}") conn.close() except Exception as e: print_error(f"Ошибка проверки системных логов: {e}") def export_data_to_csv(): """Экспорт данных в CSV (без pandas)""" try: print_section("ЭКСПОРТ ДАННЫХ В CSV") conn = get_db_connection() cursor = conn.cursor() # Создаем папку для экспорта export_dir = "database_exports" os.makedirs(export_dir, exist_ok=True) timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') export_info = [] # Получаем все таблицы cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name") tables = [row[0] for row in cursor.fetchall()] for table_name in tables: try: # Читаем данные cursor.execute(f'SELECT * FROM {table_name}') rows = cursor.fetchall() if rows: # Получаем названия колонок cursor.execute(f'PRAGMA table_info({table_name})') columns = [col[1] for col in cursor.fetchall()] # Создаем имя файла filename = f"{export_dir}/{table_name}_{timestamp}.csv" # Экспортируем в CSV with open(filename, 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(columns) # Заголовки writer.writerows(rows) # Данные # Сохраняем информацию export_info.append({ 'table': table_name, 'rows': len(rows), 'columns': len(columns), 'file': filename }) print_success(f"{table_name:<25} : {len(rows):>5} строк -> {filename}") else: print_warning(f"{table_name:<25} : Пустая таблица, пропуск") except Exception as e: print_error(f"{table_name:<25} : Ошибка экспорта: {e}") conn.close() # Создаем файл с информацией об экспорте if export_info: info_file = f"{export_dir}/export_info_{timestamp}.txt" with open(info_file, 'w', encoding='utf-8') as f: f.write(f"ЭКСПОРТ БАЗЫ ДАННЫХ\n") f.write(f"Время: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") f.write(f"Файл базы: {DATABASE_PATH}\n\n") for info in export_info: f.write(f"Таблица: {info['table']}\n") f.write(f" Строк: {info['rows']}\n") f.write(f" Колонок: {info['columns']}\n") f.write(f" Файл: {info['file']}\n\n") print_info(f"\nИнформация об экспорте сохранена в: {info_file}") return export_info except Exception as e: print_error(f"Ошибка экспорта данных: {e}") return [] def export_data_to_json(): """Экспорт данных в JSON""" try: print_section("ЭКСПОРТ ДАННЫХ В JSON") conn = get_db_connection() cursor = conn.cursor() # Создаем папку для экспорта export_dir = "database_exports" os.makedirs(export_dir, exist_ok=True) timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') export_info = [] # Получаем все таблицы cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name") tables = [row[0] for row in cursor.fetchall()] for table_name in tables: try: # Читаем данные cursor.execute(f'SELECT * FROM {table_name}') rows = cursor.fetchall() if rows: # Получаем названия колонок cursor.execute(f'PRAGMA table_info({table_name})') columns = [col[1] for col in cursor.fetchall()] # Преобразуем в список словарей data = [] for row in rows: row_dict = {} for i, column_name in enumerate(columns): row_dict[column_name] = row[i] data.append(row_dict) # Создаем имя файла filename = f"{export_dir}/{table_name}_{timestamp}.json" # Экспортируем в JSON with open(filename, 'w', encoding='utf-8') as f: json.dump({ 'table': table_name, 'columns': columns, 'count': len(data), 'data': data }, f, indent=2, ensure_ascii=False, default=str) # Сохраняем информацию export_info.append({ 'table': table_name, 'rows': len(rows), 'columns': len(columns), 'file': filename }) print_success(f"{table_name:<25} : {len(rows):>5} строк -> {filename}") else: print_warning(f"{table_name:<25} : Пустая таблица, пропуск") except Exception as e: print_error(f"{table_name:<25} : Ошибка экспорта: {e}") conn.close() return export_info except Exception as e: print_error(f"Ошибка экспорта данных: {e}") return [] def generate_summary_report(): """Генерация итогового отчета""" try: print_section("ИТОГОВЫЙ ОТЧЕТ") conn = get_db_connection() cursor = conn.cursor() report = { 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'database_file': DATABASE_PATH, 'tables': {}, 'summary': {} } # Собираем информацию по всем таблицам cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name") tables = [row[0] for row in cursor.fetchall()] total_records = 0 for table_name in tables: try: cursor.execute(f"SELECT COUNT(*) FROM {table_name}") count = cursor.fetchone()[0] report['tables'][table_name] = count total_records += count except: report['tables'][table_name] = 'error' report['summary']['total_tables'] = len(tables) report['summary']['total_records'] = total_records # Дополнительная информация try: cursor.execute("SELECT COUNT(DISTINCT user_id) FROM registrations") unique_users = cursor.fetchone()[0] report['summary']['unique_users'] = unique_users except: report['summary']['unique_users'] = 'N/A' try: cursor.execute("SELECT COUNT(*) FROM broadcasts WHERE status='completed'") completed_broadcasts = cursor.fetchone()[0] report['summary']['completed_broadcasts'] = completed_broadcasts except: report['summary']['completed_broadcasts'] = 'N/A' conn.close() # Выводим отчет print_info(f"Дата проверки: {report['timestamp']}") print_info(f"Файл базы: {report['database_file']}") print_info(f"Всего таблиц: {report['summary']['total_tables']}") print_info(f"Всего записей: {report['summary']['total_records']:,}") if 'unique_users' in report['summary'] and report['summary']['unique_users'] != 'N/A': print_info(f"Уникальных пользователей: {report['summary']['unique_users']}") print("\n📈 Статистика по таблицам:") for table, count in sorted(report['tables'].items()): if count != 'error': print(f" {table:<30} : {count:>7,}") else: print_error(f" {table:<30} : ОШИБКА") # Сохраняем отчет в файл report_file = f"database_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" with open(report_file, 'w', encoding='utf-8') as f: json.dump(report, f, indent=2, ensure_ascii=False) print_success(f"\nОтчет сохранен в файл: {report_file}") return report except Exception as e: print_error(f"Ошибка генерации отчета: {e}") return {} def show_quick_stats(): """Показывает быструю статистику""" try: print_section("БЫСТРАЯ СТАТИСТИКА") conn = get_db_connection() cursor = conn.cursor() stats = {} # Регистрации try: cursor.execute("SELECT COUNT(*) FROM registrations") stats['registrations'] = cursor.fetchone()[0] cursor.execute("SELECT COUNT(DISTINCT user_id) FROM registrations") stats['unique_users'] = cursor.fetchone()[0] except: stats['registrations'] = 'N/A' stats['unique_users'] = 'N/A' # Действия пользователей try: cursor.execute("SELECT COUNT(*) FROM user_actions") stats['user_actions'] = cursor.fetchone()[0] except: stats['user_actions'] = 'N/A' # Рассылки try: cursor.execute("SELECT COUNT(*) FROM broadcasts") stats['broadcasts'] = cursor.fetchone()[0] cursor.execute("SELECT SUM(success_count) FROM broadcasts WHERE status='completed'") stats['messages_sent'] = cursor.fetchone()[0] or 0 except: stats['broadcasts'] = 'N/A' stats['messages_sent'] = 'N/A' # amoCRM вебхуки try: cursor.execute("SELECT COUNT(*) FROM amocrm_webhook_details") stats['amocrm_webhooks'] = cursor.fetchone()[0] except: stats['amocrm_webhooks'] = 'N/A' conn.close() # Вывод статистики print("📊 СТАТИСТИКА ПРОЕКТА:") print(f" 👥 Регистрации: {stats['registrations']} ({stats['unique_users']} уникальных)") print(f" 📝 Действия пользователей: {stats['user_actions']}") print(f" 📢 Рассылки: {stats['broadcasts']} ({stats['messages_sent']} сообщений)") print(f" 🔗 amoCRM вебхуков: {stats['amocrm_webhooks']}") return stats except Exception as e: print_error(f"Ошибка получения статистики: {e}") return {} def main(): """Основная функция""" print("="*70) print("🔍 КОМПЛЕКСНАЯ ПРОВЕРКА БАЗЫ ДАННЫХ ВЕБИНАР БОТА + AMOCRM") print("="*70) # Проверяем подключение if not test_database_connection(): print_error("\nНе удалось подключиться к базе данных. Проверьте путь к файлу.") return # Показываем быструю статистику show_quick_stats() # Меню выбора while True: print_section("МЕНЮ ПРОВЕРКИ") print("1. 📋 Список всех таблиц") print("2. 👥 Проверить регистрации") print("3. 📝 Проверить действия пользователей") print("4. 📢 Проверить рассылки") print("5. 🔗 Проверить таблицы amoCRM") print("6. 📋 Проверить системные логи") print("7. 📊 Создать полный отчет") print("8. 💾 Экспортировать данные в CSV") print("9. 📄 Экспортировать данные в JSON") print("0. 🚪 Выход") choice = input("\nВыберите действие (0-9): ").strip() if choice == "0": print_success("Проверка завершена") break elif choice == "1": list_all_tables() elif choice == "2": check_registrations_table() elif choice == "3": check_user_actions_table() elif choice == "4": check_broadcasts_table() elif choice == "5": check_amocrm_tables() elif choice == "6": check_system_logs() elif choice == "7": generate_summary_report() elif choice == "8": export_data_to_csv() elif choice == "9": export_data_to_json() else: print_error("Неверный выбор. Попробуйте снова.") input("\nНажмите Enter для продолжения...") if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n\n⚠️ Проверка прервана пользователем") except Exception as e: print_error(f"Критическая ошибка: {e}") print("\n" + "="*70) print("✅ ПРОВЕРКА БАЗЫ ДАННЫХ ЗАВЕРШЕНА") print("="*70)