commit 126e76963c6af7d5d67346845175c24c348f128c Author: nini52 Date: Wed Jul 8 09:06:08 2026 +0300 Add files via upload Initial project upload diff --git a/__pycache__/config.cpython-314.pyc b/__pycache__/config.cpython-314.pyc new file mode 100644 index 0000000..ee8b1fa Binary files /dev/null and b/__pycache__/config.cpython-314.pyc differ diff --git a/__pycache__/database.cpython-314.pyc b/__pycache__/database.cpython-314.pyc new file mode 100644 index 0000000..04b736c Binary files /dev/null and b/__pycache__/database.cpython-314.pyc differ diff --git a/ai_core/__pycache__/neural_network.cpython-314.pyc b/ai_core/__pycache__/neural_network.cpython-314.pyc new file mode 100644 index 0000000..7df867f Binary files /dev/null and b/ai_core/__pycache__/neural_network.cpython-314.pyc differ 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 0000000..6e04c73 Binary files /dev/null and b/handlers/__pycache__/content.cpython-314.pyc differ diff --git a/handlers/__pycache__/menu.cpython-314.pyc b/handlers/__pycache__/menu.cpython-314.pyc new file mode 100644 index 0000000..eca2503 Binary files /dev/null and b/handlers/__pycache__/menu.cpython-314.pyc differ diff --git a/handlers/__pycache__/registration.cpython-314.pyc b/handlers/__pycache__/registration.cpython-314.pyc new file mode 100644 index 0000000..9d0fd50 Binary files /dev/null and b/handlers/__pycache__/registration.cpython-314.pyc differ diff --git a/handlers/content.py b/handlers/content.py new file mode 100644 index 0000000..c327212 --- /dev/null +++ b/handlers/content.py @@ -0,0 +1,78 @@ +from database import get_user +from ai_core.neural_network import ContentGenerator +from keyboards.reply_keyboards import get_content_keyboard, BUSINESS_TYPES +import time + +# Создаем экземпляр генератора контента +content_gen = ContentGenerator() + +def handle_content_generation(message, bot, platform_text): + """Генерирует контент для выбранной платформы""" + user_id = message.from_user.id + user = get_user(user_id) + + if not user: + bot.send_message(user_id, "❌ Ты не зарегистрирован. Напиши /start") + return + + # Извлекаем платформу из текста кнопки + platform_map = { + "📝 Пост для Instagram": "instagram", + "💼 Пост для LinkedIn": "linkedin", + "📱 Пост для Telegram": "telegram", + "🧵 Пост для Twitter/X": "twitter", + "🎯 Рекламный пост": "ad" + } + + platform = platform_map.get(platform_text, "instagram") + platform_emoji = { + "instagram": "📸", + "linkedin": "💼", + "telegram": "📱", + "twitter": "🐦", + "ad": "📢" + } + + # Получаем данные пользователя + business_type = BUSINESS_TYPES.get(str(user[4]), {}).get('name', 'Бизнес') + description = user[5] or "не указано" + + # Отправляем статус "печатает" + bot.send_chat_action(user_id, "typing") + + # Генерируем контент + try: + post = content_gen.generate_post(business_type, description, platform) + + # Отправляем результат + response_text = f""" +{platform_emoji.get(platform, '📝')} **ГОТОВЫЙ ПОСТ ДЛЯ {platform.upper()}** + +━━━━━━━━━━━━━━━━━━━━━━━ + +{post} + +━━━━━━━━━━━━━━━━━━━━━━━ + +💡 **Совет:** +• Добавь хештеги из поста +• Прикрепи фото или видео +• Укажи ссылку на свой сайт + +📌 Хочешь другой вариант? Снова нажми "💡 Предложить контент" + """ + + bot.send_message(user_id, response_text, parse_mode='Markdown') + + except Exception as e: + bot.send_message( + user_id, + f"❌ Ошибка генерации: {e}\n\nПопробуй позже или обнови описание бизнеса." + ) + + # Показываем меню выбора платформы для следующего поста + bot.send_message( + user_id, + "📱 Для какой соцсети нужен следующий пост?", + reply_markup=get_content_keyboard() + ) \ No newline at end of file diff --git a/handlers/menu.py b/handlers/menu.py new file mode 100644 index 0000000..2a3183a --- /dev/null +++ b/handlers/menu.py @@ -0,0 +1,139 @@ +from database import get_user, update_user_description +from keyboards.reply_keyboards import get_main_menu_keyboard, get_settings_keyboard, get_content_keyboard, BUSINESS_TYPES +from handlers.content import handle_content_generation + +def show_main_menu(user_id, bot): + """Показывает главное меню""" + user = get_user(user_id) + if user: + bot.send_message( + user_id, + "🏠 Главное меню\n\nВыбери действие:", + reply_markup=get_main_menu_keyboard() + ) + else: + bot.send_message( + user_id, + "❌ Ты не зарегистрирован. Напиши /start", + reply_markup=None + ) + +def handle_menu_choice(message, bot): + """Обрабатывает выбор в главном меню""" + user_id = message.from_user.id + text = message.text + + if text == "📋 Мой профиль": + show_profile(message, bot) + return True + + elif text == "✏️ Обновить описание": + # Запускаем процесс обновления описания + from handlers.registration import user_data + user_data[user_id] = {'step': 'edit_description'} + bot.send_message( + user_id, + "📝 Напиши новое описание своего бизнеса:", + reply_markup=None + ) + return True + + elif text == "📊 Статистика": + show_stats(message, bot) + return True + + elif text == "💡 Предложить контент": + # Показываем выбор платформы для контента + bot.send_message( + user_id, + "📱 Для какой соцсети нужен контент?", + reply_markup=get_content_keyboard() + ) + return True + + elif text == "⚙️ Настройки": + bot.send_message( + user_id, + "⚙️ Настройки:", + reply_markup=get_settings_keyboard() + ) + return True + + # Обработка кнопок настроек + elif text == "🔔 Включить уведомления": + bot.send_message(user_id, "✅ Уведомления включены!") + return True + + elif text == "🔕 Выключить уведомления": + bot.send_message(user_id, "🔕 Уведомления выключены!") + return True + + elif text == "📝 Сменить тему бизнеса": + bot.send_message( + user_id, + "Напиши новое описание бизнеса:", + reply_markup=None + ) + return True + + elif text == "⬅️ Назад в меню": + show_main_menu(user_id, bot) + return True + + # Обработка выбора платформы для контента + elif text in ["📝 Пост для Instagram", "💼 Пост для LinkedIn", + "📱 Пост для Telegram", "🧵 Пост для Twitter/X", + "🎯 Рекламный пост"]: + handle_content_generation(message, bot, text) + return True + + return False + +def show_profile(message, bot): + """Показывает профиль пользователя""" + user_id = message.from_user.id + user = get_user(user_id) + + if not user: + bot.send_message(user_id, "❌ Ты не зарегистрирован. Напиши /start") + return + + business_name = BUSINESS_TYPES.get(str(user[4]), {}).get('name', 'Не указан') + + profile_text = f""" +📋 **ТВОЙ ПРОФИЛЬ** +━━━━━━━━━━━━━━━━━ + +👤 **Имя:** {user[2]} +📱 **Телефон:** {user[3]} +🏢 **Вид бизнеса:** {business_name} +📝 **Описание:** +{user[5]} + +━━━━━━━━━━━━━━━━━ +💡 Хочешь обновить описание? Нажми "✏️ Обновить описание" + """ + bot.send_message(user_id, profile_text, parse_mode='Markdown') + show_main_menu(user_id, bot) + +def show_stats(message, bot): + """Показывает статистику""" + user_id = message.from_user.id + user = get_user(user_id) + + if not user: + bot.send_message(user_id, "❌ Ты не зарегистрирован. Напиши /start") + return + + stats_text = f""" +📊 **СТАТИСТИКА** + +👤 Ты зарегистрирован как предприниматель +📋 Тип: {BUSINESS_TYPES.get(str(user[4]), {}).get('name', 'Не указан')} +📝 Описание: {user[5][:50]}... + +💡 Совет: Регулярно обновляй информацию о бизнесе, +чтобы я мог давать тебе точные рекомендации! + """ + bot.send_message(user_id, stats_text, parse_mode='Markdown') + show_main_menu(user_id, bot) \ No newline at end of file diff --git a/handlers/registration.py b/handlers/registration.py new file mode 100644 index 0000000..f713952 --- /dev/null +++ b/handlers/registration.py @@ -0,0 +1,106 @@ +from handlers.menu import show_main_menu +from keyboards.reply_keyboards import get_phone_keyboard, get_business_types_keyboard, BUSINESS_TYPES +from database import get_user, save_user + +# Хранилище для временных данных пользователей +user_data = {} + +def process_registration(message, bot): + """Обработка регистрации""" + user_id = message.from_user.id + text = message.text + step = user_data[user_id].get('step', 1) + + if step == 1: + # Сохраняем имя + user_data[user_id]['name'] = text + user_data[user_id]['step'] = 2 + + bot.send_message( + user_id, + f"👋 Приятно познакомиться, {text}!\n\n" + "📱 Теперь отправь мне свой номер телефона.\n" + "Нажми на кнопку ниже 👇", + reply_markup=get_phone_keyboard() + ) + + elif step == 2: + # Сохраняем телефон + if message.contact: + phone = message.contact.phone_number + else: + phone = text + + user_data[user_id]['phone'] = phone + user_data[user_id]['step'] = 3 + + bot.send_message( + user_id, + "📋 Выбери свой вид предпринимательства:", + reply_markup=get_business_types_keyboard() + ) + + elif step == 3: + # Проверяем выбор вида бизнеса + selected_type = None + for key, value in BUSINESS_TYPES.items(): + if text == f"{value['emoji']} {key}. {value['name']}": + selected_type = int(key) + break + + if not selected_type: + bot.send_message( + user_id, + "❌ Пожалуйста, выбери вид бизнеса из кнопок ниже:", + reply_markup=get_business_types_keyboard() + ) + return + + user_data[user_id]['business_type'] = selected_type + user_data[user_id]['step'] = 4 + + bot.send_message( + user_id, + f"✅ Отлично! Ты выбрал: {BUSINESS_TYPES[str(selected_type)]['name']}\n\n" + "📝 Теперь расскажи немного о своем бизнесе:\n" + "(Чем занимаешься? Сколько лет на рынке? Какие цели?)", + reply_markup=None + ) + + elif step == 4: + # Сохраняем описание + description = text + + save_user( + user_id, + user_data[user_id]['name'], + user_data[user_id]['phone'], + user_data[user_id]['business_type'], + description + ) + + # Сохраняем вид бизнеса для дальнейшего использования + business_type_name = BUSINESS_TYPES[str(user_data[user_id]['business_type'])]['name'] + + # Очищаем временные данные + del user_data[user_id] + + welcome_text = f""" +🎉 ПОЗДРАВЛЯЮ! РЕГИСТРАЦИЯ ЗАВЕРШЕНА! + +✅ Ты зарегистрирован как предприниматель! +📋 Тип бизнеса: {business_type_name} + +💡 Теперь я буду помогать тебе: +• Генерировать контент для соцсетей +• Давать советы по бизнесу +• Анализировать твою нишу + +Нажми «💡 Предложить контент» в меню! 👇 + """ + bot.send_message(user_id, welcome_text) + show_main_menu(user_id, bot) + +def is_in_registration(user_id): + """Проверяет, находится ли пользователь в процессе регистрации""" + return user_id in user_data \ No newline at end of file diff --git a/keyboards/__pycache__/reply_keyboards.cpython-314.pyc b/keyboards/__pycache__/reply_keyboards.cpython-314.pyc new file mode 100644 index 0000000..d6631e4 Binary files /dev/null and b/keyboards/__pycache__/reply_keyboards.cpython-314.pyc differ 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 0000000..a8b665c Binary files /dev/null and b/users.db differ diff --git a/Отчет_о_разработке_бота_20260708.docx b/Отчет_о_разработке_бота_20260708.docx new file mode 100644 index 0000000..603c13e Binary files /dev/null and b/Отчет_о_разработке_бота_20260708.docx differ