From 126e76963c6af7d5d67346845175c24c348f128c Mon Sep 17 00:00:00 2001 From: nini52 Date: Wed, 8 Jul 2026 09:06:08 +0300 Subject: [PATCH] Add files via upload Initial project upload --- __pycache__/config.cpython-314.pyc | Bin 0 -> 657 bytes __pycache__/database.cpython-314.pyc | Bin 0 -> 2578 bytes .../neural_network.cpython-314.pyc | Bin 0 -> 13761 bytes ai_core/neural_network.py | 266 ++++++++++++++++++ config.py | 19 ++ create_report.py | 230 +++++++++++++++ database.py | 54 ++++ handlers/__pycache__/content.cpython-314.pyc | Bin 0 -> 3151 bytes handlers/__pycache__/menu.cpython-314.pyc | Bin 0 -> 5536 bytes .../__pycache__/registration.cpython-314.pyc | Bin 0 -> 4066 bytes handlers/content.py | 78 +++++ handlers/menu.py | 139 +++++++++ handlers/registration.py | 106 +++++++ .../reply_keyboards.cpython-314.pyc | Bin 0 -> 4037 bytes keyboards/reply_keyboards.py | 74 +++++ main.py | 211 ++++++++++++++ requirements.txt | 8 + test.py | 42 +++ users.db | Bin 0 -> 16384 bytes Отчет_о_разработке_бота_20260708.docx | Bin 0 -> 38103 bytes 20 files changed, 1227 insertions(+) create mode 100644 __pycache__/config.cpython-314.pyc create mode 100644 __pycache__/database.cpython-314.pyc create mode 100644 ai_core/__pycache__/neural_network.cpython-314.pyc create mode 100644 ai_core/neural_network.py create mode 100644 config.py create mode 100644 create_report.py create mode 100644 database.py create mode 100644 handlers/__pycache__/content.cpython-314.pyc create mode 100644 handlers/__pycache__/menu.cpython-314.pyc create mode 100644 handlers/__pycache__/registration.cpython-314.pyc create mode 100644 handlers/content.py create mode 100644 handlers/menu.py create mode 100644 handlers/registration.py create mode 100644 keyboards/__pycache__/reply_keyboards.cpython-314.pyc create mode 100644 keyboards/reply_keyboards.py create mode 100644 main.py create mode 100644 requirements.txt create mode 100644 test.py create mode 100644 users.db create mode 100644 Отчет_о_разработке_бота_20260708.docx diff --git a/__pycache__/config.cpython-314.pyc b/__pycache__/config.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee8b1fa26a6684aecd25592a34b02141421333c0 GIT binary patch literal 657 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 literal 0 HcmV?d00001 diff --git a/ai_core/neural_network.py b/ai_core/neural_network.py new file mode 100644 index 0000000..b4e8b96 --- /dev/null +++ b/ai_core/neural_network.py @@ -0,0 +1,266 @@ +import random +import os +from groq import Groq +from config import GROQ_API_KEY + +class ContentGenerator: + def __init__(self): + """Инициализация генератора контента""" + print("🔄 Инициализация ContentGenerator...") + + # Проверяем, есть ли ключ Groq + if GROQ_API_KEY: + try: + self.client = Groq(api_key=GROQ_API_KEY) + self.model = "llama-3.3-70b-versatile" + self.use_groq = True + print("✅ Groq API подключен!") + except Exception as e: + print(f"⚠️ Ошибка подключения Groq: {e}") + self.use_groq = False + else: + print("⚠️ Groq API ключ не найден, использую шаблоны") + self.use_groq = False + + # Шаблоны для запасного варианта (если Groq не работает) + self.templates = { + 'instagram': [ + "🔥 {business_name} — это не просто бизнес, это миссия!\n\n" + "Рассказываю, как мы пришли к тому, что делаем сегодня.\n" + "В {years} лет мы прошли путь от идеи до реализации.\n\n" + "А вы знали, что {business_name} помогает {problem_solution}?\n\n" + "👉 Напиши в комментариях, сталкивался ли ты с этой проблемой!\n\n" + "#бизнес #предприниматель #{hashtag} #историяуспеха", + + "📊 {business_name} — цифры, которые вдохновляют!\n\n" + "За {years} лет мы:\n" + "✅ Помогли {clients} клиентам\n" + "✅ Увеличили прибыль на {profit}%\n" + "✅ Выросли в {growth} раз\n\n" + "Хочешь так же? Пиши в DM! 💬\n\n" + "#бизнес #предпринимательство #{hashtag}" + ], + + 'linkedin': [ + "🚀 Как {business_name} изменил рынок в {years} году?\n\n" + "Когда мы начинали, казалось, что {problem} — это непреодолимая стена.\n" + "Но мы нашли решение: {solution}\n\n" + "Результат: {result} 📈\n\n" + "Какую бизнес-задачу вы решаете сегодня? Делитесь в комментариях! 💬\n\n" + "#бизнес #лидерство #{hashtag} #growth", + + "💡 5 уроков за {years} лет в бизнесе\n\n" + "1️⃣ {lesson1}\n" + "2️⃣ {lesson2}\n" + "3️⃣ {lesson3}\n" + "4️⃣ {lesson4}\n" + "5️⃣ {lesson5}\n\n" + "Какой урок оказался для вас самым важным? 👇\n\n" + "#бизнес #урокипредпринимательства #{hashtag}" + ], + + 'telegram': [ + "💬 Привет, друзья! 👋\n\n" + "Сегодня хочу поделиться мыслями о {business_name}.\n\n" + "Многие спрашивают: «Как ты пришел к этому?»\n" + "Ответ прост: {short_story}\n\n" + "А какой бизнес вдохновляет тебя? Пиши в комментариях! 👇\n\n" + "#бизнес #предприниматель #{hashtag}", + + "📌 Важный пост для предпринимателей!\n\n" + "В {business_name} мы верим, что {belief}\n\n" + "Поэтому сегодня делюсь {tip} советом:\n" + "{advice}\n\n" + "А какой совет ты бы дал себе в начале пути? 🔥\n\n" + "#бизнес #советы #{hashtag}" + ], + + 'twitter': [ + "🧵 Нить: Как {business_name} за {years} лет изменил подход к {industry}\n\n" + "1/ Мы начинали с {start_point}\n" + "2/ Главная проблема была: {problem}\n" + "3/ Решение нашли через {solution}\n" + "4/ Результат: {result}\n" + "5/ Вывод: {lesson}\n\n" + "Согласны? Репост, если цените бизнес-мышление! 🔄\n\n" + "#бизнес #{hashtag}", + + "💭 Мысль дня от {business_name}:\n\n" + "{quote}\n\n" + "Как думаете, это правда? 👇\n\n" + "#бизнес #мысли #{hashtag}" + ], + + 'ad': [ + "🎯 Хочешь получить {benefit}?\n\n" + "В {business_name} мы знаем, как это сделать!\n\n" + "За {years} лет мы помогли {clients} клиентам достичь {result}\n\n" + "Напиши «ХОЧУ» в комментариях или DM, и я расскажу как! 💬\n\n" + "#реклама #бизнес #{hashtag}" + ] + } + + print("✅ ContentGenerator готов к работе!") + + def generate_post(self, business_type, business_description, platform): + """ + Генерирует контент для соцсетей + + Args: + business_type (str): Тип бизнеса + business_description (str): Описание бизнеса + platform (str): Платформа (instagram, linkedin, telegram, twitter, ad) + + Returns: + str: Сгенерированный пост + """ + print(f"🔄 Генерация поста для {platform}...") + + # Пробуем сгенерировать через Groq + if self.use_groq: + try: + post = self._generate_with_groq(business_type, business_description, platform) + if post and len(post) > 20: + print("✅ Пост сгенерирован через Groq!") + return post + except Exception as e: + print(f"⚠️ Ошибка Groq: {e}, использую шаблоны") + + # Если Groq не работает - используем шаблоны + print("🔄 Использую шаблоны...") + return self._generate_with_templates(business_type, business_description, platform) + + def _generate_with_groq(self, business_type, business_description, platform): + """Генерация через Groq API""" + + platform_names = { + 'instagram': 'Instagram', + 'linkedin': 'LinkedIn', + 'telegram': 'Telegram', + 'twitter': 'Twitter/X', + 'ad': 'рекламный пост' + } + + prompt = f""" +Ты — профессиональный SMM-специалист и копирайтер. + +Напиши интересный, живой пост для {platform_names.get(platform, 'соцсетей')} о бизнесе. + +Тип бизнеса: {business_type} +Описание бизнеса: {business_description} + +Требования к посту: +- Длина: 100-200 слов (но не больше 200 слов) +- Живой, разговорный стиль +- Полезный контент для предпринимателей +- Призыв к действию в конце +- Используй 2-3 эмодзи + +Напиши только текст поста, без лишних пояснений. +Пост должен быть уникальным и интересным. +""" + + response = self.client.chat.completions.create( + model=self.model, + messages=[ + {"role": "system", "content": "Ты профессиональный копирайтер. Пиши ярко, полезно и вовлекающе."}, + {"role": "user", "content": prompt} + ], + temperature=0.9, + max_tokens=500 + ) + + return response.choices[0].message.content.strip() + + def _generate_with_templates(self, business_type, business_description, platform): + """Генерация через шаблоны (запасной вариант)""" + + # Если платформы нет в шаблонах - используем instagram + if platform not in self.templates: + platform = 'instagram' + + # Подготовка данных для шаблона + data = { + 'business_name': business_type, + 'industry': business_description[:30] if business_description else "твоей нише", + 'years': random.randint(2, 15), + 'clients': random.randint(50, 5000), + 'profit': random.randint(20, 300), + 'growth': random.randint(2, 10), + 'problem': random.choice([ + "не хватало знаний", "было сложно найти клиентов", + "конкуренты давили", "не было системы" + ]), + 'solution': random.choice([ + "инновационный подход", "автоматизация процессов", + "клиентоориентированность", "стратегическое планирование" + ]), + 'result': random.choice([ + "выручка выросла в 3 раза", "число клиентов удвоилось", + "бренд узнали в 5 городах", "создали команду из 30 человек" + ]), + 'problem_solution': random.choice([ + "решает главную проблему предпринимателей", + "помогает бизнесу расти быстрее", + "упрощает сложные процессы", + "делает мир лучше" + ]), + 'lesson1': "Не бойся пробовать новое", + 'lesson2': "Клиент всегда прав (почти всегда)", + 'lesson3': "Команда — это всё", + 'lesson4': "Без маркетинга никуда", + 'lesson5': "Верь в своё дело", + 'short_story': random.choice([ + "я просто начал и не остановился", + "увидел проблему и решил её", + "поверил в идею, несмотря на сомнения", + "просто делал то, что люблю" + ]), + 'belief': random.choice([ + "успех приходит к тем, кто не боится ошибаться", + "лучший способ предсказать будущее — создать его", + "качество всегда побеждает количество" + ]), + 'tip': random.choice(["простой", "важный", "ключевой"]), + 'advice': random.choice([ + "не распыляйся на всё подряд — фокусируйся на главном", + "слушай своих клиентов — они лучшие советчики", + "инвестируй в своё развитие — это окупается", + "не бойся делегировать задачи" + ]), + 'start_point': random.choice([ + "идеи и ноутбука", "небольшого стартапа", + "мечты и энтузиазма", "первых 5 клиентов" + ]), + 'quote': random.choice([ + "Бизнес — это не про деньги, а про ценность, которую ты создаёшь", + "Каждый отказ приближает тебя к успеху", + "Лучший момент начать — прямо сейчас", + "Сложно — значит ты на правильном пути" + ]), + 'benefit': random.choice([ + "прибыль без головной боли", + "стабильный доход", + "финансовую свободу", + "масштабирование бизнеса" + ]), + 'hashtag': random.choice([ + "бизнесрост", "предприниматель", "успех", + "бизнесидеи", "мойбизнес", "развитие" + ]) + } + + # Выбираем случайный шаблон для платформы + template = random.choice(self.templates[platform]) + + # Заполняем шаблон данными + try: + post = template.format(**data) + except KeyError as e: + # Если какие-то ключи отсутствуют + post = f"📝 Пост для {platform.upper()}\n\n" \ + f"Бизнес: {business_type}\n" \ + f"Описание: {business_description or 'Не указано'}\n\n" \ + f"Расскажи о своём бизнесе в комментариях! 👇\n\n#бизнес #предприниматель" + + return post \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..9e73f1a --- /dev/null +++ b/config.py @@ -0,0 +1,19 @@ +import os +from dotenv import load_dotenv + +# Загружаем переменные из .env +load_dotenv() + +# Токен бота +TOKEN = "8876908400:AAGb4_ayjfhWuUI_evP8vvc5YUUiG8jxepE" + +# Ключ Groq +GROQ_API_KEY = os.getenv("GROQ_API_KEY") + +# Проверяем, что ключ загрузился +if not GROQ_API_KEY: + print("❌ GROQ_API_KEY не найден в .env файле!") + print("👉 Создай файл .env и добавь: GROQ_API_KEY=твой_ключ") +else: + print("✅ GROQ_API_KEY загружен!") + diff --git a/create_report.py b/create_report.py new file mode 100644 index 0000000..5f431c1 --- /dev/null +++ b/create_report.py @@ -0,0 +1,230 @@ +from docx import Document +from docx.shared import Pt, Inches, RGBColor +from docx.enum.text import WD_ALIGN_PARAGRAPH +from datetime import datetime +import os + +def create_report(): + # Создаём документ + doc = Document() + + # Заголовок + title = doc.add_heading('Отчет о разработке Telegram-бота для предпринимателей', 0) + title.alignment = WD_ALIGN_PARAGRAPH.CENTER + + # Дата + doc.add_paragraph(f'Дата: {datetime.now().strftime("%d.%m.%Y")}') + doc.add_paragraph() + + # 1. Введение + doc.add_heading('1. Введение', level=1) + doc.add_heading('1.1. Назначение приложения', level=2) + doc.add_paragraph( + 'Данный Telegram-бот предназначен для помощи предпринимателям в ведении социальных сетей. ' + 'Бот собирает информацию о пользователе, его бизнесе и на основе этих данных генерирует уникальный ' + 'контент для различных социальных платформ (Instagram, LinkedIn, Telegram, Twitter/X).' + ) + + doc.add_heading('1.2. Основные функции', level=2) + doc.add_paragraph('• Регистрация пользователей с сохранением данных в SQLite', style='List Bullet') + doc.add_paragraph('• Выбор из 9 видов предпринимательской деятельности', style='List Bullet') + doc.add_paragraph('• Генерация контента для соцсетей с использованием нейросетей', style='List Bullet') + doc.add_paragraph('• Управление ботом через команды в Telegram', style='List Bullet') + doc.add_paragraph('• Интуитивно понятный интерфейс с кнопками', style='List Bullet') + + # 2. Архитектура + doc.add_heading('2. Архитектура приложения', level=1) + doc.add_heading('2.1. Структура проекта', level=2) + + doc.add_paragraph(''' + telegram_bot/ + ├── .env # Переменные окружения + ├── config.py # Загрузка конфигурации + ├── database.py # Работа с SQLite + ├── main.py # Точка входа + ├── requirements.txt # Список библиотек + ├── ai_core/ + │ ├── __init__.py + │ └── neural_network.py # Нейросеть + ├── handlers/ + │ ├── __init__.py + │ ├── registration.py + │ ├── menu.py + │ └── content.py + └── keyboards/ + ├── __init__.py + └── reply_keyboards.py + ''', style='Normal') + + # 3. Библиотеки + doc.add_heading('3. Используемые библиотеки', level=1) + doc.add_heading('3.1. Основные зависимости', level=2) + + libs = [ + ('pytelegrambotapi', 'Работа с Telegram Bot API'), + ('sqlite3', 'Легковесная база данных (встроенная)'), + ('python-dotenv', 'Загрузка переменных из .env'), + ('requests', 'HTTP-запросы к API'), + ('groq', 'API для работы с нейросетями Groq'), + ('python-docx', 'Создание Word-документов'), + ] + + table = doc.add_table(rows=1, cols=2) + table.style = 'Table Grid' + hdr_cells = table.rows[0].cells + hdr_cells[0].text = 'Библиотека' + hdr_cells[1].text = 'Назначение' + + for lib, desc in libs: + row_cells = table.add_row().cells + row_cells[0].text = lib + row_cells[1].text = desc + + doc.add_paragraph() + + # 4. База данных + doc.add_heading('4. База данных', level=1) + doc.add_heading('4.1. Схема таблиц', level=2) + + doc.add_paragraph('Таблица users:') + table2 = doc.add_table(rows=1, cols=3) + table2.style = 'Table Grid' + hdr = table2.rows[0].cells + hdr[0].text = 'Поле' + hdr[1].text = 'Тип' + hdr[2].text = 'Описание' + + fields = [ + ('id', 'INTEGER PRIMARY KEY', 'Уникальный ID записи'), + ('telegram_id', 'INTEGER UNIQUE', 'ID пользователя в Telegram'), + ('name', 'TEXT', 'Имя пользователя'), + ('phone', 'TEXT', 'Номер телефона'), + ('business_type', 'INTEGER', 'ID вида бизнеса (1-9)'), + ('description', 'TEXT', 'Описание бизнеса'), + ('registered', 'BOOLEAN', 'Флаг завершения регистрации'), + ] + + for field, typ, desc in fields: + row = table2.add_row().cells + row[0].text = field + row[1].text = typ + row[2].text = desc + + # 5. Виды бизнеса + doc.add_heading('4.2. 9 видов предпринимательства', level=2) + + business_types = [ + ('1', '🛒 Розничная торговля'), + ('2', '🏭 Производство'), + ('3', '💻 IT-услуги'), + ('4', '📚 Образование'), + ('5', '🏥 Медицина'), + ('6', '🚚 Логистика'), + ('7', '🏨 Гостиничный бизнес'), + ('8', '🎨 Маркетинг и реклама'), + ('9', '🔧 Услуги (ремонт, клининг)'), + ] + + table3 = doc.add_table(rows=1, cols=2) + table3.style = 'Table Grid' + hdr = table3.rows[0].cells + hdr[0].text = 'ID' + hdr[1].text = 'Название' + + for bid, bname in business_types: + row = table3.add_row().cells + row[0].text = bid + row[1].text = bname + + # 6. Управление + doc.add_heading('5. Управление ботом', level=1) + doc.add_heading('5.1. Команды Telegram', level=2) + + table4 = doc.add_table(rows=1, cols=2) + table4.style = 'Table Grid' + hdr = table4.rows[0].cells + hdr[0].text = 'Команда' + hdr[1].text = 'Описание' + + commands = [ + ('/start', 'Начать работу / открыть меню'), + ('/help', 'Показать справку'), + ('/status', 'Показать статус бота'), + ('/stop', 'Остановить бота'), + ('/restart', 'Перезапустить бота'), + ] + + for cmd, desc in commands: + row = table4.add_row().cells + row[0].text = cmd + row[1].text = desc + + # 7. Нейросеть + doc.add_heading('6. Нейросетевая составляющая', level=1) + doc.add_heading('6.1. Используемые модели', level=2) + + table5 = doc.add_table(rows=1, cols=3) + table5.style = 'Table Grid' + hdr = table5.rows[0].cells + hdr[0].text = 'Модель' + hdr[1].text = 'Провайдер' + hdr[2].text = 'Назначение' + + models = [ + ('llama-3.3-70b-versatile', 'Groq', 'Генерация постов'), + ('mixtral-8x7b-32768', 'Groq', 'Альтернативная модель'), + ] + + for model, provider, purpose in models: + row = table5.add_row().cells + row[0].text = model + row[1].text = provider + row[2].text = purpose + + # 8. Установка + doc.add_heading('7. Установка и запуск', level=1) + + doc.add_heading('7.1. Установка зависимостей', level=2) + doc.add_paragraph('pip install -r requirements.txt', style='Normal') + + doc.add_heading('7.2. Настройка переменных окружения', level=2) + doc.add_paragraph('.env:') + doc.add_paragraph('TELEGRAM_TOKEN=ваш_токен_от_BotFather', style='Normal') + doc.add_paragraph('GROQ_API_KEY=gsk_ваш_ключ_из_console.groq.com', style='Normal') + + doc.add_heading('7.3. Запуск', level=2) + doc.add_paragraph('python main.py', style='Normal') + + # 9. Примеры + doc.add_heading('8. Примеры работы', level=1) + doc.add_paragraph('Сценарий регистрации:') + doc.add_paragraph('1. Пользователь вводит /start', style='List Number') + doc.add_paragraph('2. Бот запрашивает имя', style='List Number') + doc.add_paragraph('3. Бот запрашивает телефон (кнопка)', style='List Number') + doc.add_paragraph('4. Бот показывает 9 видов бизнеса (кнопки)', style='List Number') + doc.add_paragraph('5. Бот запрашивает описание бизнеса', style='List Number') + doc.add_paragraph('6. Регистрация завершена → главное меню', style='List Number') + + # 10. Заключение + doc.add_heading('9. Заключение', level=1) + doc.add_paragraph( + 'Разработанный Telegram-бот представляет собой полностью функциональное решение ' + 'для предпринимателей, желающих автоматизировать создание контента для социальных сетей.' + ) + + doc.add_heading('Ключевые достижения:', level=2) + doc.add_paragraph('• Модульная архитектура', style='List Bullet') + doc.add_paragraph('• Интеграция с нейросетями (Groq)', style='List Bullet') + doc.add_paragraph('• Удобный интерфейс с кнопками', style='List Bullet') + doc.add_paragraph('• Локальное хранение данных (SQLite)', style='List Bullet') + doc.add_paragraph('• Гибкая система шаблонов', style='List Bullet') + doc.add_paragraph('• Управление через Telegram-команды', style='List Bullet') + + # Сохраняем + filename = f'Отчет_о_разработке_бота_{datetime.now().strftime("%Y%m%d")}.docx' + doc.save(filename) + print(f'✅ Отчет создан: {filename}') + print(f'📁 Файл сохранен в: {os.path.abspath(filename)}') + +if __name__ == '__main__': + create_report() \ No newline at end of file diff --git a/database.py b/database.py new file mode 100644 index 0000000..24d3611 --- /dev/null +++ b/database.py @@ -0,0 +1,54 @@ +import sqlite3 + +def create_db(): + conn = sqlite3.connect('users.db') + cursor = conn.cursor() + + cursor.execute(''' + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + telegram_id INTEGER UNIQUE, + name TEXT, + phone TEXT, + business_type INTEGER, + description TEXT, + registered BOOLEAN DEFAULT 0 + ) + ''') + + conn.commit() + conn.close() + print("✅ База данных создана!") + +def save_user(telegram_id, name, phone, business_type, description): + conn = sqlite3.connect('users.db') + cursor = conn.cursor() + + cursor.execute(''' + INSERT OR REPLACE INTO users (telegram_id, name, phone, business_type, description, registered) + VALUES (?, ?, ?, ?, ?, 1) + ''', (telegram_id, name, phone, business_type, description)) + + conn.commit() + conn.close() + print(f"✅ Пользователь {name} сохранен!") + +def get_user(telegram_id): + conn = sqlite3.connect('users.db') + cursor = conn.cursor() + + cursor.execute('SELECT * FROM users WHERE telegram_id = ?', (telegram_id,)) + user = cursor.fetchone() + + conn.close() + return user + +def update_user_description(telegram_id, description): + conn = sqlite3.connect('users.db') + cursor = conn.cursor() + cursor.execute('UPDATE users SET description = ? WHERE telegram_id = ?', (description, telegram_id)) + conn.commit() + conn.close() + +# Создаем базу при первом импорте +create_db() \ No newline at end of file diff --git a/handlers/__pycache__/content.cpython-314.pyc b/handlers/__pycache__/content.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e04c73c639bbf40e68e0e0c5167594febd163e1 GIT binary patch literal 3151 zcmb_eU2GKB6~41GJ3Bl3=h$mwgUybOVpzK}s&SzOR77JJ8?a@Koh3=PtOoDc+1R@~ zogWd@J}jn99XU!|plYfL45Uq6MN!rSh-0vc)J965dZ&xD+bK~a`cU<4BT!qlFFkj5 z#!eIZ)Q;Epo_p{4Ki`?T-Qf_A;Q7hdhF^FyfY6`G!hJjr@$e`R1#}XL)DRk^bSg$@ z&yZ)3)@hrjhnPXH?j2-x)?PD1KHc|ix*hd7Ds)ctZb7DQi zt3cO1mCxyNPCp{&WL47hYTRQ*$@xTWKQ%3%IhB{xv=#ow(_=#;17l;U@n=T|#zrP+ z#|W87G_YnKegxhZPy&s9=FlZa-N@Vxm=!wdb(aackE+oMlVEl_+f$7QwW0(y>T~%v z=L9WMeU8=`Pv0iL&&lL`Ict5M- z0JV_`$Z#uyIHQUm@)6mz<5G~1Mpsh|Z9~aA_hhuer8egiFDKYOr-}+MHYI$I^De=P zTU?z%BsM45QK-o09~W`J(URa{+}i6?0*|lSi38#`v2~wgIriUc8%wshc3l0Uuqj9C zEudtR%fq5{JIRm|9DgiY#%Zx_JP5vR@1@;{VyF#pqXZ8HkN4N+43$9#=r)w0;_U{3 zF}{Fr;x&BJEZ`NhV4eeNR=}%x9j}?Qv7zXvP@(Dg2uI19|SDUiQTH1!Dh63lnuY!0so zyER=>^$}w`sHrYqxFq03Pz_S97ehJVm{O&z<zw-s|A|S zat`l>d!{@vhKb_HaS>64N<5uGjeAuoHZXaGr&~d0<*K z&k<-BVF$QLBLGpv@0+tc51<9`{{n3O(DnruH|)lGx7INLdfNf0mpOY#fQU#d!LF?l z-vZ362px93n7DeAbRTel1JF94?LT_6gBP5~;)W%4I-NhAgAX6CNUA2MviY=ZJPCER z8}c$~Fh~{PMSxy(+rDVN1lue71w#Z*o+nVpcfm5G70_ij`8ojX7HMTCMI_@jw;^A^ zO&Z%q;0j?{1~vz%xY%P1gIdT6G~C77dxQX%L}90G-FyjTp`s-9YhV!U;5Cxa+az}L zocXHxGAOM1LEZ$1Ai$t1D>G+OSqRxs;vvgFsphlxXW#N<(kglTT0u?DrBhj1)1)cc zqT#!*vSgpubk(Y}4=0|N^prHAXYx5K;9d%*QCi$E2PXw`ea_srgZs5-SUxZNGg-I7(!UVjnk~8Se(1E!Y-APv-uY? zR_K(WWpdzl3YuBA0%=*BP&2k!i?Q7asj{Zzb5LR14kc^kBi-5A>4HHJtgk$^KlwD6 z)sn+wL&<(wo7VG6(tWd~z}@8YQZ7A1IGo6PlrvUKZFA#>b+zmF!HA7p3&Mu%& z!j0u{%nZlM;SMw0Q8;ox(6Df%6lg8<|0NKqaDg({Y;w)7Z^0e%J#O+3T)4_1e|)LC z!tGqz>I}P<;uWrIslOUvqio@LwGP#_mLoAU61x&w`fe$5pfLCe*RYVNaPtFp+;m6>Lf0XMJgy2o@^*==6_eq?JovdfI@T59{?nNnnA zj;XR#8&#nqWvaoX8Wsj$pDa;NV$_K{2R~~5-S*#ZFAY752cN4V=35j6VS3mCTSdIj zUkyZBf^(s22l5Bqe5@SBT=PBdNVVR!9yOV0g@c5hxZfBrHFj5h$lLfg#CX|%Jc^)T z<0ByXjdWIm4VCbo;^E?+Dnk2?d0-43_x#;U`}t214F9Uq!2VB-+%10XJ>1a07yV{$ zV4$7;kZKxer9W)-0v+cqE-mTODG2~#_eztLfs(6oPfj*eX(pAE_0xHES|#5qtHr%0 zYdy8L+gRIeQ0pp2&tzqln6-iOEA$XZq;?Sn+(CE~88hSNUQ fG1~Jdbo7rX@F|NTu~Jwl1RgO16ve7v2Cjbt6YX)R literal 0 HcmV?d00001 diff --git a/handlers/__pycache__/menu.cpython-314.pyc b/handlers/__pycache__/menu.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eca2503c4be0ba5bff2cc8601d675cdbe91e72ca GIT binary patch literal 5536 zcmc&&|8o@O8Q;6x%k6#11(Jj05M&cDct8`1G-6~xEokCE8aE+e=W6EQmXHFMb9b*u z$LSne#VSKmz?o=`1jMP%*l7TxQ6T;cyXK~eJLy2FosK{CD%hX!8Qq^qB@fC4)jl~T zD+%(s*BL)WS%H5K$MH9ZP|0#}7d6t;!)>tZX?Kr%mDR{4mvh`wuE*7hKBZ3&<}vPd zS~u7g$^EdcOS87(&V4-+U#c7PX4b-teny|vKi9|fPmMS9i})QkUJ~_7`ejrv>Q^Bg z7xgRpxPH|*k=cX}`7?u~qJFBZLLi`@gqaI4lGP_f{bTg|%s6Vi1XC0GcjC|KWDrl!W(>js*j=bI6|19o@5CBlPtEYO`<-6z`j7+YjDu4 zY6(T_hERUf?Kr_{9#XGV(d^pwL?gOl?^Ze%=6-wJl1~yO|Gd3wSq#kcT;=GO z@f>7&&gm%cArxQeSSXy1+dWp^gQaksmXtkru~fw@EwWE+`Ir{mHirxEp;z^7y=qvm z+PnISl%3&4tf#fMh}C*_)!*i!_7RAZSOe?<__6g|J)RA7_<}W)76XCnGMgdS-_=nW%q3hururVB)fIygTzC zwNS+uF0Yl&kU@^%6;3%A5C0GF<``IB!7D$-9s>x|{ft>8u<|l*9)0W4P zVg#`bGn6YaD;h@uI*=-c>66jZ2(FeKw$%l6B(NHJ4#zwI>?_neOlB{LjAIF!Z>D!3V#<_ z{F6upm&r2(gRH}icU}?o_sWT}`~@>K#5d|QO>B&(--HKjl6&&eTymsSS$^&gbY zMNVpLQslmVRkH|?vKS5&AP#2+m^#L%sR|_)h4>K5mx>>?nAh|(vrixIiK`v>~>%8Cd9!J4XpPG!04;YHKouKO$Xg^%X^kN!h=Xy*QvdgDfY*(0y{4Pi-f z+TQJCq?aK6!FWi#zZz-q`*Xj+OIpG<{@#8uF<3+-*oY3tEH|PAD3qnRkp1i}D*5&-` zW`)H=hjYS8^k$y(oV&W^7UvGM+^XRG4Wp~Z_?++)NdFdGphPhHMI41z7CD2zsjwya zJ{)C^-}bl*{1^tB`>VF=UWMJQU%&PC2hVQ9uff(Z;8ae-kT1Y@33dnm*TyMoPc#gy;k$C~W#krb{EVUyZA+2|d`2)-ZGVhbZ z4+`1J@b3dUk0G$vEP`@(#F?#ZbADO{d17iz~6`D_0#8FW%qbLKvvxU3RKZ8{T03zs;bHcu_gz(pqhUrM-myyQv z>IWOfTz`7_y%)!%smR9Z$R;DQX`)BpwtFh_Y<5SU=j*ET0#{Qz^!%HvhN5}Sb>EVi zCHD_MKeB3=-d5Dl)HjV*0jk!yuDiV1#4EK~f1cw5-u%K)M96N>FX6nxG#@c|;Q!dK zbv}~gpP1!=-hbi6+fj_pAVab4|1*k7p8q+H0lOR=voWg(nIvBcP6_LA@4Ev|t(5#y z;GS?Qn2BMI%iAHqqt5XAbRaMy1M zHp8~A9z@Ow9w&&};#d-u2hteF$s2Ad=g|5^tEe;}00nnoE>mZR0+v~dCt_>IH|rtp z$V{MYYHFgO=o)aAAuU*Zt3|&q0abyx@QV*Ebgyw>1C7MT5Dg(6QRg7=r zYXinHM2pV&hC&yIE2v*0f=OR+=yG;kWTU}n8LALY5#PfLT}tQ%!I&y_ARqcfJp&qL zC4yHTpn@`R%v%;U0*v2TAW_WN6e7K>IE;!qisFZ01kV2A@GXI>S~eXPzYL4#Yeu_2 zsDFRgdrLo1ro!u|!!1U*W$ah_7HKNnrB`+X4R*TfX6lv>KQrPR^^AmueghzA^yY*9 zY9ae{J~AH&e$Ig4u_7Soh=omou9ABa_%uZKUxi0uMxC#RDhMxq!z#S9PfZrPCE&0y zcR_(3+aDAe>9y#uNLma+X^uYR7ywx`SJ(tF&m5FDD-S^g^x;&R{k+HJa$VzEu5m}E hxFdh%TE6AOuE4kAHkWJRw;k@NtNvC?#8uA>{TK3ZWXb>l literal 0 HcmV?d00001 diff --git a/handlers/__pycache__/registration.cpython-314.pyc b/handlers/__pycache__/registration.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d0fd50392419f66da85e51517db6866de87f9e6 GIT binary patch literal 4066 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 literal 0 HcmV?d00001 diff --git a/keyboards/reply_keyboards.py b/keyboards/reply_keyboards.py new file mode 100644 index 0000000..c5905a5 --- /dev/null +++ b/keyboards/reply_keyboards.py @@ -0,0 +1,74 @@ +from telebot.types import ReplyKeyboardMarkup, KeyboardButton + +# === 9 ВИДОВ ПРЕДПРИНИМАТЕЛЕЙ === +BUSINESS_TYPES = { + '1': {'name': '🛒 Розничная торговля', 'emoji': '🛒'}, + '2': {'name': '🏭 Производство', 'emoji': '🏭'}, + '3': {'name': '💻 IT-услуги', 'emoji': '💻'}, + '4': {'name': '📚 Образование', 'emoji': '📚'}, + '5': {'name': '🏥 Медицина', 'emoji': '🏥'}, + '6': {'name': '🚚 Логистика', 'emoji': '🚚'}, + '7': {'name': '🏨 Гостиничный бизнес', 'emoji': '🏨'}, + '8': {'name': '🎨 Маркетинг и реклама', 'emoji': '🎨'}, + '9': {'name': '🔧 Услуги (ремонт, клининг)', 'emoji': '🔧'} +} + +def get_main_menu_keyboard(): + """Главное меню после регистрации""" + keyboard = ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) + keyboard.add( + KeyboardButton("📋 Мой профиль"), + KeyboardButton("✏️ Обновить описание"), + KeyboardButton("📊 Статистика"), + KeyboardButton("💡 Предложить контент"), + KeyboardButton("⚙️ Настройки") + ) + return keyboard + +def get_business_types_keyboard(): + """Клавиатура с 9 видами предпринимателей""" + keyboard = ReplyKeyboardMarkup(row_width=3, resize_keyboard=True) + buttons = [] + for key, value in BUSINESS_TYPES.items(): + buttons.append(KeyboardButton(f"{value['emoji']} {key}. {value['name']}")) + + row1 = buttons[0:3] + row2 = buttons[3:6] + row3 = buttons[6:9] + + keyboard.add(*row1) + keyboard.add(*row2) + keyboard.add(*row3) + + return keyboard + +def get_phone_keyboard(): + """Клавиатура с запросом номера телефона""" + keyboard = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True) + button = KeyboardButton("📱 Отправить номер телефона", request_contact=True) + keyboard.add(button) + return keyboard + +def get_settings_keyboard(): + """Клавиатура настроек""" + keyboard = ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) + keyboard.add( + KeyboardButton("🔔 Включить уведомления"), + KeyboardButton("🔕 Выключить уведомления"), + KeyboardButton("📝 Сменить тему бизнеса"), + KeyboardButton("⬅️ Назад в меню") + ) + return keyboard + +def get_content_keyboard(): + """Клавиатура для генерации контента""" + keyboard = ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) + keyboard.add( + KeyboardButton("📝 Пост для Instagram"), + KeyboardButton("💼 Пост для LinkedIn"), + KeyboardButton("📱 Пост для Telegram"), + KeyboardButton("🧵 Пост для Twitter/X"), + KeyboardButton("🎯 Рекламный пост"), + KeyboardButton("⬅️ Назад в меню") + ) + return keyboard \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..ea05d8d --- /dev/null +++ b/main.py @@ -0,0 +1,211 @@ +import telebot +import requests +import sys +import os +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry +from telebot import apihelper + +from config import TOKEN +from database import get_user +from handlers.registration import process_registration, is_in_registration +from handlers.menu import show_main_menu, handle_menu_choice +from keyboards.reply_keyboards import get_main_menu_keyboard + +# === НАСТРОЙКА ДЛЯ ОБХОДА БЛОКИРОВОК === +session = requests.Session() +retry = Retry(total=5, backoff_factor=1) +adapter = HTTPAdapter(max_retries=retry) +session.mount('https://', adapter) + +apihelper.session = session +apihelper.CONNECT_TIMEOUT = 30 +apihelper.READ_TIMEOUT = 30 + +# === ИНИЦИАЛИЗАЦИЯ БОТА === +bot = telebot.TeleBot(TOKEN) + +# === ФЛАГ ДЛЯ УПРАВЛЕНИЯ БОТОМ === +bot_running = True + +# === КОМАНДА /start === +@bot.message_handler(commands=['start']) +def start(message): + user_id = message.from_user.id + user = get_user(user_id) + + if user: + bot.send_message( + user_id, + f"👋 С возвращением, {user[2]}!", + reply_markup=get_main_menu_keyboard() + ) + return + + # Начинаем регистрацию + from handlers.registration import user_data as reg_data + reg_data[user_id] = {'step': 1} + bot.send_message( + user_id, + "👋 Привет! Я твой бизнес-помощник.\n\n" + "Давай познакомимся! Как тебя зовут?\n" + "(Напиши своё имя)" + ) + +# === КОМАНДА /stop - ОСТАНОВИТЬ БОТА (ДЛЯ ВСЕХ) === +@bot.message_handler(commands=['stop']) +def stop_bot(message): + user_id = message.from_user.id + global bot_running + + bot_running = False + + bot.send_message(user_id, "🛑 Вы остановилибота...") + print(f"🛑 Бот остановлен пользователем {user_id}") + + # Останавливаем бота + bot.stop_polling() + os._exit(0) + +# === КОМАНДА /restart - ПЕРЕЗАПУСТИТЬ БОТА (ДЛЯ ВСЕХ) === +@bot.message_handler(commands=['restart']) +def restart_bot(message): + user_id = message.from_user.id + + bot.send_message(user_id, "🔄 Перезапускаю бота...") + print(f"🔄 Перезапуск бота пользователем {user_id}") + + # Перезапускаем + bot.stop_polling() + os.execv(sys.executable, ['python'] + sys.argv) + +# === КОМАНДА /status - СТАТУС БОТА (ДЛЯ ВСЕХ) === +@bot.message_handler(commands=['status']) +def status_bot(message): + user_id = message.from_user.id + + import datetime + now = datetime.datetime.now().strftime("%d.%m.%Y %H:%M:%S") + + # Проверяем, есть ли GROQ_API_KEY + try: + from config import GROQ_API_KEY + groq_status = "подключен ✅" if GROQ_API_KEY else "не подключен ⚠️" + except: + groq_status = "не подключен ⚠️" + + status_text = f""" +📊 **СТАТУС БОТА** + +🟢 Состояние: **Активен** ✅ +📅 Текущее время: {now} + +📋 **Информация:** +• Бот запущен и работает +• База данных: подключена ✅ +• Groq API: {groq_status} + +💡 **Команды управления:** +/stop - остановить бота +/restart - перезапустить бота +/status - этот статус + """ + bot.send_message(user_id, status_text, parse_mode='Markdown') + +# === КОМАНДА /help - ПОМОЩЬ === +@bot.message_handler(commands=['help']) +def help_command(message): + user_id = message.from_user.id + + help_text = """ +🤖 **ПОМОЩЬ ПО БОТУ** + +📋 **Основные команды:** +/start - начать работу или открыть меню +/help - показать эту справку +/status - статус бота +/stop - остановить бота +/restart - перезапустить бота + +📱 **Меню после регистрации:** +📋 Мой профиль - посмотреть свои данные +✏️ Обновить описание - изменить описание бизнеса +📊 Статистика - статистика +💡 Предложить контент - сгенерировать пост для соцсетей +⚙️ Настройки - настройки бота + +💡 **Как использовать:** +1. Напиши /start +2. Пройди регистрацию +3. Используй кнопки меню +4. Нажми "💡 Предложить контент" для генерации поста + """ + bot.send_message(user_id, help_text, parse_mode='Markdown') + +# === ОБРАБОТКА ВСЕХ СООБЩЕНИЙ === +@bot.message_handler(func=lambda message: True) +def handle_messages(message): + global bot_running + + if not bot_running: + bot.send_message(message.chat.id, "🛑 Бот остановлен. Напиши /restart для перезапуска.") + return + + user_id = message.from_user.id + text = message.text + + # Проверяем, зарегистрирован ли пользователь + user = get_user(user_id) + + if user: + # Если пользователь в процессе обновления описания + from handlers.registration import user_data as reg_data + if user_id in reg_data and reg_data[user_id].get('step') == 'edit_description': + from database import update_user_description + update_user_description(user_id, text) + del reg_data[user_id] + bot.send_message( + user_id, + "✅ Описание обновлено!", + reply_markup=get_main_menu_keyboard() + ) + return + + # Обрабатываем выбор в меню + if handle_menu_choice(message, bot): + return + + # Если ничего не подошло - показываем меню + bot.send_message( + user_id, + "Используй кнопки меню 👇", + reply_markup=get_main_menu_keyboard() + ) + return + + # Если пользователь НЕ зарегистрирован - регистрируем + if is_in_registration(user_id): + process_registration(message, bot) + else: + bot.send_message( + user_id, + "❌ Ты не зарегистрирован. Напиши /start" + ) + +# === ЗАПУСК БОТА === +if __name__ == '__main__': + print("🤖 БОТ ЗАПУЩЕН!") + print("📋 Команды:") + print(" /start - начать работу") + print(" /help - помощь") + print(" /status - статус бота") + print(" /stop - остановить бота") + print(" /restart - перезапустить бота") + print("✅ Используй кнопки для навигации") + + try: + bot.infinity_polling(timeout=30) + except KeyboardInterrupt: + print("🛑 Бот остановлен вручную (Ctrl+C)") + except Exception as e: + print(f"❌ Ошибка: {e}") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..32af77c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +pytelegrambotapi>=4.16.0 +sqlalchemy>=2.0.23 +python-dotenv>=1.0.0 +requests>=2.31.0 +urllib3>=2.1.0 +groq>=0.5.0 +transformers>=4.36.0 # (опционально, для локальных моделей) +torch>=2.1.0 # (опционально, для локальных моделей) \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..db38cf1 --- /dev/null +++ b/test.py @@ -0,0 +1,42 @@ +import telebot +from config import TOKEN +import requests +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry +from telebot import apihelper + +# === ОБХОД БЛОКИРОВКИ === +session = requests.Session() +retry = Retry(total=5, backoff_factor=1) +adapter = HTTPAdapter(max_retries=retry) +session.mount('https://', adapter) +session.mount('http://', adapter) + +apihelper.session = session +apihelper.CONNECT_TIMEOUT = 30 +apihelper.READ_TIMEOUT = 30 + +bot = telebot.TeleBot(TOKEN) + +@bot.message_handler(commands=['start']) +def start(message): + bot.send_message(message.chat.id, "✅ БОТ РАБОТАЕТ! Я тебя слышу!") + +@bot.message_handler(func=lambda message: True) +def echo(message): + bot.send_message(message.chat.id, f"Ты написал: {message.text}") + +print("🔄 Проверяю подключение к Telegram...") + +# Проверяем подключение +try: + me = bot.get_me() + print(f"✅ Подключено! Бот: @{me.username}") +except Exception as e: + print(f"❌ НЕ ПОДКЛЮЧЕНО! Ошибка: {e}") + print("👉 Включите VPN!") + exit() + +print("🚀 Бот готов к работе! Напиши /start") + +bot.infinity_polling(timeout=30) \ No newline at end of file diff --git a/users.db b/users.db new file mode 100644 index 0000000000000000000000000000000000000000..a8b665c5bb02f37a4fcebe56b704a9940c92db62 GIT binary patch literal 16384 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 U5U_*3?kY(L4%ms<#IN7}0qvrQXaE2J literal 0 HcmV?d00001