From f2117bbeb46af52194b2bb7b5e3a117db01a2a31 Mon Sep 17 00:00:00 2001 From: harold Date: Thu, 6 Feb 2025 10:55:41 +0500 Subject: [PATCH] add fix for bot --- config.ini => gemini_worker/main.py | 0 src/__init__.py => gemini_worker/schemas.py | 0 src/advatroniks.session-journal | Bin 57968 -> 0 bytes src/core/database/chats.py | 9 -- src/main.py | 90 ------------------ telegram-application/.dockerignore | 1 + .gitignore => telegram-application/.gitignore | 2 +- telegram-application/Dockerfile | 19 ++++ .../core => telegram-application}/__init__.py | 0 ai_test.py => telegram-application/ai_test.py | 3 - .../config.ini | 0 telegram-application/docker-compose.yml | 54 +++++++++++ .../poetry.lock | 52 +++++++++- .../pyproject.toml | 4 +- .../readme.md | 0 .../src}/__init__.py | 0 .../src/core}/__init__.py | 0 .../src/core/ai_services}/__init__.py | 0 .../src}/core/ai_services/base.py | 0 .../src/core/ai_services/gemini}/__init__.py | 0 .../core/ai_services/gemini/check_limiter.py | 6 ++ .../src}/core/ai_services/gemini/constants.py | 41 +++++--- .../src/core/ai_services/gemini/schemas.py | 13 +++ .../src}/core/ai_services/gemini/service.py | 6 +- .../src}/core/ai_services/google.py | 0 .../src/core/ai_services/groq/__init__.py | 0 .../src}/core/ai_services/groq/constants.py | 0 .../src}/core/ai_services/groq/service.py | 0 .../src}/core/ai_services/schemas.py | 14 +-- .../src/core/common/__init__.py | 0 .../src}/core/common/constants.py | 0 .../src}/core/common/promt.py | 0 .../src/core/common/schemas.py | 17 ++++ .../src}/core/database/__init__.py | 4 +- .../src}/core/database/base.py | 9 +- .../src/core/database/chats.py | 8 ++ .../src}/core/database/connect.py | 0 .../src}/core/database/tg_messages.py | 2 +- .../src}/core/database/users.py | 5 - .../src/core/rabbitmq/__init__.py | 0 .../src/core/rabbitmq/connect.py | 14 +++ .../src/core/redis_helper/__init__.py | 0 .../src/core/redis_helper/redis_connect.py | 11 +++ .../src/core/settings/__init__.py | 0 .../src}/core/settings/base.py | 6 +- .../src}/core/settings/database.py | 0 .../src}/core/settings/gemini.py | 0 .../src}/core/settings/groq.py | 0 .../src/core/settings/rabbitmq.py | 7 ++ .../src/core/settings/redis.py | 8 ++ .../src/core/tg_service/__init__.py | 0 .../src/core/tg_service/constants.py | 1 + .../src/core/tg_service/crud.py | 42 ++++++++ .../src/core/tg_service/messages_handler.py | 44 +++++++++ .../src/core/tg_service/schemas.py | 9 ++ .../src/core/tg_service/service.py | 55 +++++++++++ .../src/core/tg_service/utils.py | 13 +++ telegram-application/src/main.py | 25 +++++ 58 files changed, 450 insertions(+), 144 deletions(-) rename config.ini => gemini_worker/main.py (100%) rename src/__init__.py => gemini_worker/schemas.py (100%) delete mode 100644 src/advatroniks.session-journal delete mode 100644 src/core/database/chats.py delete mode 100644 src/main.py create mode 100644 telegram-application/.dockerignore rename .gitignore => telegram-application/.gitignore (99%) create mode 100644 telegram-application/Dockerfile rename {src/core => telegram-application}/__init__.py (100%) rename ai_test.py => telegram-application/ai_test.py (83%) rename src/core/ai_services/__init__.py => telegram-application/config.ini (100%) create mode 100644 telegram-application/docker-compose.yml rename poetry.lock => telegram-application/poetry.lock (94%) rename pyproject.toml => telegram-application/pyproject.toml (84%) rename src/core/ai_services/gemini/__init__.py => telegram-application/readme.md (100%) rename {src/core/ai_services/groq => telegram-application/src}/__init__.py (100%) rename {src/core/api_telegram => telegram-application/src/core}/__init__.py (100%) rename {src/core/common => telegram-application/src/core/ai_services}/__init__.py (100%) rename {src => telegram-application/src}/core/ai_services/base.py (100%) rename {src/core/settings => telegram-application/src/core/ai_services/gemini}/__init__.py (100%) create mode 100644 telegram-application/src/core/ai_services/gemini/check_limiter.py rename {src => telegram-application/src}/core/ai_services/gemini/constants.py (77%) create mode 100644 telegram-application/src/core/ai_services/gemini/schemas.py rename {src => telegram-application/src}/core/ai_services/gemini/service.py (90%) rename {src => telegram-application/src}/core/ai_services/google.py (100%) create mode 100644 telegram-application/src/core/ai_services/groq/__init__.py rename {src => telegram-application/src}/core/ai_services/groq/constants.py (100%) rename {src => telegram-application/src}/core/ai_services/groq/service.py (100%) rename {src => telegram-application/src}/core/ai_services/schemas.py (51%) create mode 100644 telegram-application/src/core/common/__init__.py rename {src => telegram-application/src}/core/common/constants.py (100%) rename {src => telegram-application/src}/core/common/promt.py (100%) create mode 100644 telegram-application/src/core/common/schemas.py rename {src => telegram-application/src}/core/database/__init__.py (65%) rename {src => telegram-application/src}/core/database/base.py (63%) create mode 100644 telegram-application/src/core/database/chats.py rename {src => telegram-application/src}/core/database/connect.py (100%) rename {src => telegram-application/src}/core/database/tg_messages.py (90%) rename {src => telegram-application/src}/core/database/users.py (66%) create mode 100644 telegram-application/src/core/rabbitmq/__init__.py create mode 100644 telegram-application/src/core/rabbitmq/connect.py create mode 100644 telegram-application/src/core/redis_helper/__init__.py create mode 100644 telegram-application/src/core/redis_helper/redis_connect.py create mode 100644 telegram-application/src/core/settings/__init__.py rename {src => telegram-application/src}/core/settings/base.py (79%) rename {src => telegram-application/src}/core/settings/database.py (100%) rename {src => telegram-application/src}/core/settings/gemini.py (100%) rename {src => telegram-application/src}/core/settings/groq.py (100%) create mode 100644 telegram-application/src/core/settings/rabbitmq.py create mode 100644 telegram-application/src/core/settings/redis.py create mode 100644 telegram-application/src/core/tg_service/__init__.py create mode 100644 telegram-application/src/core/tg_service/constants.py create mode 100644 telegram-application/src/core/tg_service/crud.py create mode 100644 telegram-application/src/core/tg_service/messages_handler.py create mode 100644 telegram-application/src/core/tg_service/schemas.py create mode 100644 telegram-application/src/core/tg_service/service.py create mode 100644 telegram-application/src/core/tg_service/utils.py create mode 100644 telegram-application/src/main.py diff --git a/config.ini b/gemini_worker/main.py similarity index 100% rename from config.ini rename to gemini_worker/main.py diff --git a/src/__init__.py b/gemini_worker/schemas.py similarity index 100% rename from src/__init__.py rename to gemini_worker/schemas.py diff --git a/src/advatroniks.session-journal b/src/advatroniks.session-journal deleted file mode 100644 index dc9a95dee1b8a211a508da630f8c594fd76f78db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57968 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 UphX5H1^H$9!0|-Ra?rj20N0sQBme*a diff --git a/src/core/database/chats.py b/src/core/database/chats.py deleted file mode 100644 index 3c71c07..0000000 --- a/src/core/database/chats.py +++ /dev/null @@ -1,9 +0,0 @@ -from sqlalchemy.orm import Mapped - -from src.core.database import Base - - -class TgChat(Base): - telegram_chat_id: Mapped[int] - chat_type: Mapped[str] - title: Mapped[str] \ No newline at end of file diff --git a/src/main.py b/src/main.py deleted file mode 100644 index eb29ed0..0000000 --- a/src/main.py +++ /dev/null @@ -1,90 +0,0 @@ -import json -from time import sleep - -from pyrogram import Client, filters -from pyrogram.enums import ChatType -from pyrogram.types import Message - -from ai_test import create_request_ai -from src.core.ai_services.gemini.service import gemini_helper -from src.core.ai_services.groq.service import groq_helper -from src.core.ai_services.schemas import MessageFromChatSchema -from src.core.common.promt import BASE_MESSAGE - -api_id = 17718565 -api_hash = "72f93973f4227415572f039d4f847082" - -app = Client( - name="advatroniks", - api_id=api_id, - api_hash=api_hash, -) - -DATA: dict[int, list[MessageFromChatSchema]] = dict() - - -@app.on_message(filters.all) # Используем фильтр для сообщений из всех чатов -async def listen_messages(client: Client, message: Message): - # print(message.chat) - chat_title = message.chat.title or message.chat.first_name or message.chat.username - sender = message.from_user.first_name if message.from_user else "Система/Бот" - text = message.text or "[не текстовое сообщение]" - - - - if message.chat.type not in [ChatType.PRIVATE, ChatType.BOT] and message.from_user and message.text: - if DATA.get(message.chat.id): - DATA[message.chat.id].append( - MessageFromChatSchema( - message_id=message.id, - user_id=message.from_user.id, - chat_id=message.chat.id, - text=message.text, - date=message.date - ) - ) - else: - DATA[message.chat.id] = [ - MessageFromChatSchema( - message_id=message.id, - user_id=message.from_user.id, - chat_id=message.chat.id, - text=message.text, - date=message.date - ) - ] - print(len(DATA[message.chat.id])) - - # print(chat_title, '|', len(DATA[message.chat.id])) - # print(len(DATA[message.chat.id])) - counter = 0 - - for key, value in DATA.items(): - if len(value) == 20 and counter == 0: - - gemini_response = await gemini_helper.create_request_ai( - messages=value - ) - # print(gemini_response) - # print("*" * 100, "GEMINI", "*" * 100) - - groq_response = await groq_helper.create_request_ai( - messages=value, - ) - sleep(20) - # print(groq_response) - # print("*" * 100, "GROQ", "*" * 100) - - for _ in value: - print(_) - counter += 1 - - # print(f"Сообщение из чата: {chat_title}") - # print(f"Отправитель: {sender}") - # print(f"Текст: {text}") - # print("-" * 40) - -# Запуск клиента -if __name__ == "__main__": - print("Слушаю все сообщения из чатов...") - app.run() \ No newline at end of file diff --git a/telegram-application/.dockerignore b/telegram-application/.dockerignore new file mode 100644 index 0000000..f5e96db --- /dev/null +++ b/telegram-application/.dockerignore @@ -0,0 +1 @@ +venv \ No newline at end of file diff --git a/.gitignore b/telegram-application/.gitignore similarity index 99% rename from .gitignore rename to telegram-application/.gitignore index 40dabe0..7682f5f 100644 --- a/.gitignore +++ b/telegram-application/.gitignore @@ -2,7 +2,7 @@ __pycache__/ *.py[cod] *$py.class -.idea +../.idea # C extensions *.so diff --git a/telegram-application/Dockerfile b/telegram-application/Dockerfile new file mode 100644 index 0000000..c355cf1 --- /dev/null +++ b/telegram-application/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.12-slim + +# Устанавливаем зависимости для Poetry +RUN pip install poetry + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем файлы Poetry (pyproject.toml и poetry.lock) +COPY pyproject.toml poetry.lock ./ + +# Устанавливаем зависимости через Poetry +RUN poetry install --no-dev --no-interaction + +# Копируем весь код приложения +COPY . . + +# Команда для запуска приложения +CMD ["poetry", "run", "python", "bot.py"] diff --git a/src/core/__init__.py b/telegram-application/__init__.py similarity index 100% rename from src/core/__init__.py rename to telegram-application/__init__.py diff --git a/ai_test.py b/telegram-application/ai_test.py similarity index 83% rename from ai_test.py rename to telegram-application/ai_test.py index 2bf8968..a5e4838 100644 --- a/ai_test.py +++ b/telegram-application/ai_test.py @@ -1,8 +1,5 @@ -import asyncio - from groq import AsyncGroq -from src.core.common.promt import ROLE, ANALYTIC_PROMT from src.core.settings.base import settings # Убедитесь, что переменная окружения GROQ_API_KEY установлена diff --git a/src/core/ai_services/__init__.py b/telegram-application/config.ini similarity index 100% rename from src/core/ai_services/__init__.py rename to telegram-application/config.ini diff --git a/telegram-application/docker-compose.yml b/telegram-application/docker-compose.yml new file mode 100644 index 0000000..673efff --- /dev/null +++ b/telegram-application/docker-compose.yml @@ -0,0 +1,54 @@ +version: "3.8" + +services: + bot: + build: . + container_name: pyrogram_bot + restart: unless-stopped + environment: + - DB_HOST=postgres + - DB_NAME=mydatabase + - DB_USER=user + - DB_PASSWORD=password + - REDIS_HOST=redis + - RABBITMQ_HOST=rabbitmq + depends_on: + - postgres + - redis + - rabbitmq + + postgres: + image: postgres:13 + container_name: postgres + restart: unless-stopped + environment: + POSTGRES_DB: mydatabase + POSTGRES_USER: user + POSTGRES_PASSWORD: password + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + + # Сервис для Redis + redis: + image: redis:latest + container_name: redis + restart: unless-stopped + ports: + - "6379:6379" + + # Сервис для RabbitMQ + rabbitmq: + image: "rabbitmq:3-management" + container_name: rabbitmq + restart: unless-stopped + ports: + - "5672:5672" + - "15672:15672" + environment: + RABBITMQ_DEFAULT_USER: guest + RABBITMQ_DEFAULT_PASS: guest + +volumes: + postgres_data: diff --git a/poetry.lock b/telegram-application/poetry.lock similarity index 94% rename from poetry.lock rename to telegram-application/poetry.lock index 2677ff7..8336010 100644 --- a/poetry.lock +++ b/telegram-application/poetry.lock @@ -198,6 +198,56 @@ files = [ {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, ] +[[package]] +name = "fast-depends" +version = "2.4.12" +description = "FastDepends - extracted and cleared from HTTP domain logic FastAPI Dependency Injection System. Async and sync are both supported." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "fast_depends-2.4.12-py3-none-any.whl", hash = "sha256:9e5d110ddc962329e46c9b35e5fe65655984247a13ee3ca5a33186db7d2d75c2"}, + {file = "fast_depends-2.4.12.tar.gz", hash = "sha256:9393e6de827f7afa0141e54fa9553b737396aaf06bd0040e159d1f790487b16d"}, +] + +[package.dependencies] +anyio = ">=3.0.0,<5.0.0" +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<3.0.0" + +[[package]] +name = "faststream" +version = "0.5.34" +description = "FastStream: the simplest way to work with a messaging queues" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "faststream-0.5.34-py3-none-any.whl", hash = "sha256:aa7f61d6968a68f13ebf755cce9e8bf11b00717c28b2ef66e896b5d652a6c6a2"}, + {file = "faststream-0.5.34.tar.gz", hash = "sha256:84615968c5768ebaa89b72ae66b53e5302c08e7d18b341ef5193e54cb6ba8623"}, +] + +[package.dependencies] +anyio = ">=3.7.1,<5" +fast-depends = ">=2.4.0b0,<3.0.0" +typing-extensions = ">=4.8.0" + +[package.extras] +cli = ["typer (>=0.9,!=0.12,<=0.15.1)", "watchfiles (>=0.15.0,<1.1.0)"] +confluent = ["confluent-kafka (>=2,<3)", "confluent-kafka (>=2.6,<3)"] +dev = ["aio-pika (>=9,<10)", "aiokafka (>=0.9,<0.13)", "bandit (==1.8.0)", "cairosvg", "codespell (==2.3.0)", "confluent-kafka (>=2,<3)", "confluent-kafka (>=2.6,<3)", "confluent-kafka-stubs", "coverage[toml] (==7.6.1)", "coverage[toml] (==7.6.10)", "detect-secrets (==1.5.0)", "dirty-equals (==0.8.0)", "email-validator (==2.2.0)", "fastapi (==0.115.6)", "httpx (==0.28.1)", "mdx-include (==1.4.2)", "mike (==2.1.3)", "mkdocs-git-revision-date-localized-plugin (==1.3.0)", "mkdocs-glightbox (==0.4.0)", "mkdocs-literate-nav (==0.6.1)", "mkdocs-macros-plugin (==1.3.7)", "mkdocs-material (==9.5.49)", "mkdocs-minify-plugin (==0.8.0)", "mkdocs-static-i18n (==1.2.3)", "mkdocstrings[python] (==0.27.0)", "mypy (==1.14.1)", "nats-py (>=2.7.0,<=3.0.0)", "opentelemetry-sdk (>=1.24.0,<2.0.0)", "pillow", "pre-commit (==3.5.0)", "pre-commit (==4.0.1)", "prometheus-client (>=0.20.0,<0.30.0)", "pydantic-settings (>=2.0.0,<3.0.0)", "pytest (==8.3.4)", "pytest-asyncio (==0.24.0)", "pytest-asyncio (==0.25.1)", "pyyaml (==6.0.2)", "redis (>=5.0.0,<6.0.0)", "requests", "ruff (==0.8.6)", "semgrep (==1.101.0)", "typer (>=0.9,!=0.12,<=0.15.1)", "types-aiofiles", "types-deprecated", "types-docutils", "types-pygments", "types-pyyaml", "types-redis", "types-setuptools", "types-ujson", "typing-extensions (>=4.8.0,<4.12.1)", "watchfiles (>=0.15.0,<1.1.0)"] +devdocs = ["cairosvg", "mdx-include (==1.4.2)", "mike (==2.1.3)", "mkdocs-git-revision-date-localized-plugin (==1.3.0)", "mkdocs-glightbox (==0.4.0)", "mkdocs-literate-nav (==0.6.1)", "mkdocs-macros-plugin (==1.3.7)", "mkdocs-material (==9.5.49)", "mkdocs-minify-plugin (==0.8.0)", "mkdocs-static-i18n (==1.2.3)", "mkdocstrings[python] (==0.27.0)", "pillow", "requests"] +kafka = ["aiokafka (>=0.9,<0.13)"] +lint = ["aio-pika (>=9,<10)", "aiokafka (>=0.9,<0.13)", "bandit (==1.8.0)", "codespell (==2.3.0)", "confluent-kafka (>=2,<3)", "confluent-kafka (>=2.6,<3)", "confluent-kafka-stubs", "mypy (==1.14.1)", "nats-py (>=2.7.0,<=3.0.0)", "opentelemetry-sdk (>=1.24.0,<2.0.0)", "prometheus-client (>=0.20.0,<0.30.0)", "redis (>=5.0.0,<6.0.0)", "ruff (==0.8.6)", "semgrep (==1.101.0)", "typer (>=0.9,!=0.12,<=0.15.1)", "types-aiofiles", "types-deprecated", "types-docutils", "types-pygments", "types-pyyaml", "types-redis", "types-setuptools", "types-ujson", "watchfiles (>=0.15.0,<1.1.0)"] +nats = ["nats-py (>=2.7.0,<=3.0.0)"] +optionals = ["aio-pika (>=9,<10)", "aiokafka (>=0.9,<0.13)", "confluent-kafka (>=2,<3)", "confluent-kafka (>=2.6,<3)", "nats-py (>=2.7.0,<=3.0.0)", "opentelemetry-sdk (>=1.24.0,<2.0.0)", "prometheus-client (>=0.20.0,<0.30.0)", "redis (>=5.0.0,<6.0.0)", "typer (>=0.9,!=0.12,<=0.15.1)", "watchfiles (>=0.15.0,<1.1.0)"] +otel = ["opentelemetry-sdk (>=1.24.0,<2.0.0)"] +prometheus = ["prometheus-client (>=0.20.0,<0.30.0)"] +rabbit = ["aio-pika (>=9,<10)"] +redis = ["redis (>=5.0.0,<6.0.0)"] +test-core = ["coverage[toml] (==7.6.1)", "coverage[toml] (==7.6.10)", "dirty-equals (==0.8.0)", "pytest (==8.3.4)", "pytest-asyncio (==0.24.0)", "pytest-asyncio (==0.25.1)", "typing-extensions (>=4.8.0,<4.12.1)"] +testing = ["coverage[toml] (==7.6.1)", "coverage[toml] (==7.6.10)", "dirty-equals (==0.8.0)", "email-validator (==2.2.0)", "fastapi (==0.115.6)", "httpx (==0.28.1)", "pydantic-settings (>=2.0.0,<3.0.0)", "pytest (==8.3.4)", "pytest-asyncio (==0.24.0)", "pytest-asyncio (==0.25.1)", "pyyaml (==6.0.2)", "typing-extensions (>=4.8.0,<4.12.1)"] +types = ["aio-pika (>=9,<10)", "aiokafka (>=0.9,<0.13)", "confluent-kafka (>=2,<3)", "confluent-kafka (>=2.6,<3)", "confluent-kafka-stubs", "mypy (==1.14.1)", "nats-py (>=2.7.0,<=3.0.0)", "opentelemetry-sdk (>=1.24.0,<2.0.0)", "prometheus-client (>=0.20.0,<0.30.0)", "redis (>=5.0.0,<6.0.0)", "typer (>=0.9,!=0.12,<=0.15.1)", "types-aiofiles", "types-deprecated", "types-docutils", "types-pygments", "types-pyyaml", "types-redis", "types-setuptools", "types-ujson", "watchfiles (>=0.15.0,<1.1.0)"] + [[package]] name = "google-ai-generativelanguage" version = "0.6.15" @@ -1237,4 +1287,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.1" python-versions = ">=3.11, <4.0" -content-hash = "dc59c68a2f05dcce182f7343c2fe7979ad2b654211954f9480a263cd9e128232" +content-hash = "ae3423d56de9fa2b9ea991f7cfb550df3b945bbe0f489024da70b663dd17221b" diff --git a/pyproject.toml b/telegram-application/pyproject.toml similarity index 84% rename from pyproject.toml rename to telegram-application/pyproject.toml index 346bf0a..a50bbc7 100644 --- a/pyproject.toml +++ b/telegram-application/pyproject.toml @@ -2,6 +2,7 @@ name = "scrapper-tg-bot" version = "0.1.0" description = "" +package-mode = false authors = [ {name = "harold",email = "tihon414@gmail.com"} ] @@ -16,7 +17,8 @@ dependencies = [ "sqlalchemy (>=2.0.37,<3.0.0)", "pydantic-settings (>=2.7.1,<3.0.0)", "redis (>=5.2.1,<6.0.0)", - "google-generativeai (>=0.8.4,<0.9.0)" + "google-generativeai (>=0.8.4,<0.9.0)", + "faststream[rabbitmq] (>=0.5.34,<0.6.0)" ] diff --git a/src/core/ai_services/gemini/__init__.py b/telegram-application/readme.md similarity index 100% rename from src/core/ai_services/gemini/__init__.py rename to telegram-application/readme.md diff --git a/src/core/ai_services/groq/__init__.py b/telegram-application/src/__init__.py similarity index 100% rename from src/core/ai_services/groq/__init__.py rename to telegram-application/src/__init__.py diff --git a/src/core/api_telegram/__init__.py b/telegram-application/src/core/__init__.py similarity index 100% rename from src/core/api_telegram/__init__.py rename to telegram-application/src/core/__init__.py diff --git a/src/core/common/__init__.py b/telegram-application/src/core/ai_services/__init__.py similarity index 100% rename from src/core/common/__init__.py rename to telegram-application/src/core/ai_services/__init__.py diff --git a/src/core/ai_services/base.py b/telegram-application/src/core/ai_services/base.py similarity index 100% rename from src/core/ai_services/base.py rename to telegram-application/src/core/ai_services/base.py diff --git a/src/core/settings/__init__.py b/telegram-application/src/core/ai_services/gemini/__init__.py similarity index 100% rename from src/core/settings/__init__.py rename to telegram-application/src/core/ai_services/gemini/__init__.py diff --git a/telegram-application/src/core/ai_services/gemini/check_limiter.py b/telegram-application/src/core/ai_services/gemini/check_limiter.py new file mode 100644 index 0000000..51dca9c --- /dev/null +++ b/telegram-application/src/core/ai_services/gemini/check_limiter.py @@ -0,0 +1,6 @@ + + + + +async def check_limiter(): + diff --git a/src/core/ai_services/gemini/constants.py b/telegram-application/src/core/ai_services/gemini/constants.py similarity index 77% rename from src/core/ai_services/gemini/constants.py rename to telegram-application/src/core/ai_services/gemini/constants.py index a65a6eb..aff718d 100644 --- a/src/core/ai_services/gemini/constants.py +++ b/telegram-application/src/core/ai_services/gemini/constants.py @@ -6,16 +6,21 @@ ROLE = """ ANALYTIC_PROMT = """ Ты получаешь json с такими полями { - "messages": [ - { - "message_id": integer, - "user_id": integer, - "chat_id": integer, - "text": string, - "date": datetime - } - ] -} + chats: [ + "chat_id": integer + "messages": [ + { + "user_id: integer, + "message_id": integer, + "text": string, + "date": datetime + } + ] + + ] +} + +chats - это список чатов. messages - это срез диалога в чате телеграмма. пользователи могут общаться на абсолютно разные темы. Твоя задача: @@ -27,16 +32,24 @@ messages - это срез диалога в чате телеграмма. ВАЖНО: Если ты уверен на 100 процентов, что они заинтересованы в подобных услугах и им можно предложить, то верни. +Условно в нескольких чатах может быть несколько потенциальных клиентов, тогда вот так выведи + { - "user_id": integer, - "chat_id": integer, - "reason": string + success: [ + { + "user_id": integer, + "chat_id": integer, + "reason": string + } + ] } поле reason: Кратко(до 100 симоволов) почему ты решил, что это потенциальный клиент. Если ты хотя бы чуть чуть не уверен, то верни вот такую строку -{"user_id": null, "chat_id": null, "reason": null} +{ + success: null +} ВАЖНО: Ты должен вернуть ТОЛЬКО JSON и не словом больше. Иначе я разорюсь. diff --git a/telegram-application/src/core/ai_services/gemini/schemas.py b/telegram-application/src/core/ai_services/gemini/schemas.py new file mode 100644 index 0000000..2056eaf --- /dev/null +++ b/telegram-application/src/core/ai_services/gemini/schemas.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel + +from src.core.ai_services.schemas import MessageFromChatSchema + + +class ChatMessageSchema(MessageFromChatSchema): + chat_id: int + messages: list[MessageFromChatSchema] + + +class FullRequestForGeminiSchema(BaseModel): + chats: list[ChatMessageSchema] + diff --git a/src/core/ai_services/gemini/service.py b/telegram-application/src/core/ai_services/gemini/service.py similarity index 90% rename from src/core/ai_services/gemini/service.py rename to telegram-application/src/core/ai_services/gemini/service.py index 51f0ac2..40931da 100644 --- a/src/core/ai_services/gemini/service.py +++ b/telegram-application/src/core/ai_services/gemini/service.py @@ -5,6 +5,7 @@ from src.core.ai_services.base import BaseAiService import google.generativeai as genai from src.core.ai_services.gemini.constants import GEMINI_BASE_MESSAGE +from src.core.ai_services.gemini.schemas import FullRequestForGeminiSchema from src.core.ai_services.schemas import MessageFromChatSchema, ResponseFromAiSchema from src.core.settings.base import settings @@ -23,12 +24,11 @@ class GoogleHelper(BaseAiService): @staticmethod def _serialize_messages_to_promt( - messages: list[MessageFromChatSchema], + chats: FullRequestForGeminiSchema, ) -> list[dict]: messages_for_request = GEMINI_BASE_MESSAGE.copy() - dumped_messages = [msg.model_dump_with_datetime() for msg in messages] - text_for_request = json.dumps({"messages": dumped_messages}) + text_for_request = json.dumps(chats.model_dump()) extend_message = { "role": "user", diff --git a/src/core/ai_services/google.py b/telegram-application/src/core/ai_services/google.py similarity index 100% rename from src/core/ai_services/google.py rename to telegram-application/src/core/ai_services/google.py diff --git a/telegram-application/src/core/ai_services/groq/__init__.py b/telegram-application/src/core/ai_services/groq/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/core/ai_services/groq/constants.py b/telegram-application/src/core/ai_services/groq/constants.py similarity index 100% rename from src/core/ai_services/groq/constants.py rename to telegram-application/src/core/ai_services/groq/constants.py diff --git a/src/core/ai_services/groq/service.py b/telegram-application/src/core/ai_services/groq/service.py similarity index 100% rename from src/core/ai_services/groq/service.py rename to telegram-application/src/core/ai_services/groq/service.py diff --git a/src/core/ai_services/schemas.py b/telegram-application/src/core/ai_services/schemas.py similarity index 51% rename from src/core/ai_services/schemas.py rename to telegram-application/src/core/ai_services/schemas.py index 36902c9..1efec56 100644 --- a/src/core/ai_services/schemas.py +++ b/telegram-application/src/core/ai_services/schemas.py @@ -2,19 +2,15 @@ from datetime import datetime from pydantic import BaseModel, PositiveInt, NegativeInt +from src.core.common.schemas import BaseModelWithSerializeDatetime -class MessageFromChatSchema(BaseModel): - message_id: PositiveInt + +class MessageFromChatSchema(BaseModelWithSerializeDatetime): + id: PositiveInt user_id: PositiveInt chat_id: NegativeInt text: str - date: datetime - - def model_dump_with_datetime(self) -> dict: - dumped_model = self.model_dump() - dumped_model["date"] = dumped_model["date"].isoformat() - - return dumped_model + message_time: datetime class ResponseFromAiSchema(BaseModel): diff --git a/telegram-application/src/core/common/__init__.py b/telegram-application/src/core/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/core/common/constants.py b/telegram-application/src/core/common/constants.py similarity index 100% rename from src/core/common/constants.py rename to telegram-application/src/core/common/constants.py diff --git a/src/core/common/promt.py b/telegram-application/src/core/common/promt.py similarity index 100% rename from src/core/common/promt.py rename to telegram-application/src/core/common/promt.py diff --git a/telegram-application/src/core/common/schemas.py b/telegram-application/src/core/common/schemas.py new file mode 100644 index 0000000..cd7a393 --- /dev/null +++ b/telegram-application/src/core/common/schemas.py @@ -0,0 +1,17 @@ +from datetime import datetime + +from pydantic import BaseModel, field_validator + + +class BaseModelWithSerializeDatetime(BaseModel): + @field_validator("*") + def remove_tzinfo(cls, value): + if isinstance(value, datetime) and value.tzinfo is not None: + return value.replace(tzinfo=None) + return value + + class Config: + json_encoders = { + datetime: lambda v: f"{v.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-5]}Z" + } + diff --git a/src/core/database/__init__.py b/telegram-application/src/core/database/__init__.py similarity index 65% rename from src/core/database/__init__.py rename to telegram-application/src/core/database/__init__.py index f88eba6..54146cc 100644 --- a/src/core/database/__init__.py +++ b/telegram-application/src/core/database/__init__.py @@ -2,9 +2,11 @@ __all__ = [ "Base", "TgMessage", "TgChat", + "User", ] from .base import Base from .tg_messages import TgMessage -from .chats import TgChat \ No newline at end of file +from .chats import TgChat +from .users import User \ No newline at end of file diff --git a/src/core/database/base.py b/telegram-application/src/core/database/base.py similarity index 63% rename from src/core/database/base.py rename to telegram-application/src/core/database/base.py index dcbab03..785c69f 100644 --- a/src/core/database/base.py +++ b/telegram-application/src/core/database/base.py @@ -1,6 +1,6 @@ from uuid import uuid4, UUID -from sqlalchemy import Uuid as Alq_uuid, text +from sqlalchemy import text, BigInteger from sqlalchemy.orm import DeclarativeBase, declared_attr, Mapped, mapped_column @@ -11,9 +11,8 @@ class Base(DeclarativeBase): def __tablename__(cls) -> str: return f"{cls.__name__.lower()}s" - id: Mapped[UUID] = mapped_column( - Alq_uuid, - default=uuid4, - server_default=text("uuid_generate_v4()"), + id: Mapped[int] = mapped_column( + BigInteger, primary_key=True, + unique=True, ) diff --git a/telegram-application/src/core/database/chats.py b/telegram-application/src/core/database/chats.py new file mode 100644 index 0000000..f98d748 --- /dev/null +++ b/telegram-application/src/core/database/chats.py @@ -0,0 +1,8 @@ +from sqlalchemy.orm import Mapped, mapped_column + +from src.core.database import Base + + +class TgChat(Base): + chat_type: Mapped[str] + title: Mapped[str] \ No newline at end of file diff --git a/src/core/database/connect.py b/telegram-application/src/core/database/connect.py similarity index 100% rename from src/core/database/connect.py rename to telegram-application/src/core/database/connect.py diff --git a/src/core/database/tg_messages.py b/telegram-application/src/core/database/tg_messages.py similarity index 90% rename from src/core/database/tg_messages.py rename to telegram-application/src/core/database/tg_messages.py index 108edd6..e4e2cca 100644 --- a/src/core/database/tg_messages.py +++ b/telegram-application/src/core/database/tg_messages.py @@ -11,7 +11,7 @@ class TgMessage(Base): text: Mapped[str] message_time: Mapped[datetime] user_id: Mapped[int] = mapped_column( - ForeignKey("users.telegram_id"), + ForeignKey("users.id"), ) chat_id: Mapped[int] = mapped_column( ForeignKey("chats.telegram_chat_id"), diff --git a/src/core/database/users.py b/telegram-application/src/core/database/users.py similarity index 66% rename from src/core/database/users.py rename to telegram-application/src/core/database/users.py index 183e71e..cf8f23b 100644 --- a/src/core/database/users.py +++ b/telegram-application/src/core/database/users.py @@ -5,11 +5,6 @@ from src.core.database.base import Base class User(Base): - telegram_id: Mapped[int] = mapped_column( - BigInteger, - primary_key=True, - unique=True, - ) username: Mapped[str] first_name: Mapped[str | None] last_name: Mapped[str | None] diff --git a/telegram-application/src/core/rabbitmq/__init__.py b/telegram-application/src/core/rabbitmq/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/telegram-application/src/core/rabbitmq/connect.py b/telegram-application/src/core/rabbitmq/connect.py new file mode 100644 index 0000000..e489f55 --- /dev/null +++ b/telegram-application/src/core/rabbitmq/connect.py @@ -0,0 +1,14 @@ +from faststream.rabbit import RabbitBroker, RabbitExchange, ExchangeType, QueueType, RabbitQueue + +broker = RabbitBroker() + + +base_exchange = RabbitExchange( + name="base_exchange", + type=ExchangeType.DIRECT, +) + +base_queue = RabbitQueue( + name="base_queue", + queue_type=QueueType.CLASSIC, +) diff --git a/telegram-application/src/core/redis_helper/__init__.py b/telegram-application/src/core/redis_helper/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/telegram-application/src/core/redis_helper/redis_connect.py b/telegram-application/src/core/redis_helper/redis_connect.py new file mode 100644 index 0000000..5c26da9 --- /dev/null +++ b/telegram-application/src/core/redis_helper/redis_connect.py @@ -0,0 +1,11 @@ +from redis.asyncio import ConnectionPool, Redis + +from src.core.settings.base import settings + +redis_pool = ConnectionPool( + host=settings.REDIS.HOST, + port=settings.REDIS.PORT, + decode_responses=True +) + +redis_client = Redis(connection_pool=redis_pool) \ No newline at end of file diff --git a/telegram-application/src/core/settings/__init__.py b/telegram-application/src/core/settings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/core/settings/base.py b/telegram-application/src/core/settings/base.py similarity index 79% rename from src/core/settings/base.py rename to telegram-application/src/core/settings/base.py index 56d60e4..e16e492 100644 --- a/src/core/settings/base.py +++ b/telegram-application/src/core/settings/base.py @@ -5,7 +5,8 @@ from src.core.common.constants import PydanticEnvPrefixEnum, EnvFileLocation, En from src.core.settings.database import DatabaseSettings from src.core.settings.gemini import GeminiSettings from src.core.settings.groq import GroqSettings - +from src.core.settings.rabbitmq import RabbitmqSettings +from src.core.settings.redis import RedisSettings print(EnvFileLocation.PRODUCTION) @@ -26,5 +27,8 @@ class Settings(BaseSettings): GROQ: GroqSettings GEMINI: GeminiSettings + REDIS: RedisSettings + RABBIT: RabbitmqSettings + settings = Settings() # type:ignore \ No newline at end of file diff --git a/src/core/settings/database.py b/telegram-application/src/core/settings/database.py similarity index 100% rename from src/core/settings/database.py rename to telegram-application/src/core/settings/database.py diff --git a/src/core/settings/gemini.py b/telegram-application/src/core/settings/gemini.py similarity index 100% rename from src/core/settings/gemini.py rename to telegram-application/src/core/settings/gemini.py diff --git a/src/core/settings/groq.py b/telegram-application/src/core/settings/groq.py similarity index 100% rename from src/core/settings/groq.py rename to telegram-application/src/core/settings/groq.py diff --git a/telegram-application/src/core/settings/rabbitmq.py b/telegram-application/src/core/settings/rabbitmq.py new file mode 100644 index 0000000..ddeb665 --- /dev/null +++ b/telegram-application/src/core/settings/rabbitmq.py @@ -0,0 +1,7 @@ +from typing import Annotated + +from pydantic import BaseModel, AmqpDsn, AfterValidator + + +class RabbitmqSettings(BaseModel): + URL: Annotated[AmqpDsn, AfterValidator(str)] \ No newline at end of file diff --git a/telegram-application/src/core/settings/redis.py b/telegram-application/src/core/settings/redis.py new file mode 100644 index 0000000..eea63ba --- /dev/null +++ b/telegram-application/src/core/settings/redis.py @@ -0,0 +1,8 @@ +from typing import Annotated + +from pydantic import BaseModel, RedisDsn, AfterValidator + + +class RedisSettings(BaseModel): + HOST: str + PORT: int diff --git a/telegram-application/src/core/tg_service/__init__.py b/telegram-application/src/core/tg_service/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/telegram-application/src/core/tg_service/constants.py b/telegram-application/src/core/tg_service/constants.py new file mode 100644 index 0000000..1614011 --- /dev/null +++ b/telegram-application/src/core/tg_service/constants.py @@ -0,0 +1 @@ +MESSAGE_CHANG_SIZE: int = 20 \ No newline at end of file diff --git a/telegram-application/src/core/tg_service/crud.py b/telegram-application/src/core/tg_service/crud.py new file mode 100644 index 0000000..326928f --- /dev/null +++ b/telegram-application/src/core/tg_service/crud.py @@ -0,0 +1,42 @@ +from sqlalchemy import insert +from sqlalchemy.ext.asyncio import AsyncSession + +from src.core.ai_services.schemas import MessageFromChatSchema +from src.core.database import User, TgChat, TgMessage + + +async def create_new_user( + session: AsyncSession, + **kwargs +) -> User: + new_user = User(**kwargs) + + session.add(new_user) + await session.commit() + return new_user + + +async def create_new_chat( + session: AsyncSession, + **kwargs +) -> TgChat: + new_chat = TgChat(**kwargs) + session.add(new_chat) + await session.commit() + + return new_chat + + +async def bulk_insert_messages( + messages: list[MessageFromChatSchema], + session: AsyncSession, +) -> None: + stmt = ( + insert(TgMessage), + [ + *[message.model_dump() for message in messages], + ] + ) + await session.execute(*stmt) + await session.commit() + diff --git a/telegram-application/src/core/tg_service/messages_handler.py b/telegram-application/src/core/tg_service/messages_handler.py new file mode 100644 index 0000000..6c073cf --- /dev/null +++ b/telegram-application/src/core/tg_service/messages_handler.py @@ -0,0 +1,44 @@ +from pyrogram import filters, Client +from pyrogram.enums import ChatType +from pyrogram.types import Message + +from src.core.ai_services.schemas import MessageFromChatSchema +from src.core.tg_service.constants import MESSAGE_CHANG_SIZE +from src.core.tg_service.service import check_user_exists, check_chat_exists +from src.core.tg_service import utils as api_tg_utils + + +DATA: dict[int, list[MessageFromChatSchema]] = dict() + + +async def some_publisher(): + pass + + +async def message_listener(client: Client, message: Message): + if api_tg_utils.check_message_condition(message): + await check_user_exists( + user_pyrogram=message.from_user, + ) + await check_chat_exists( + chat_pyrogram=message.chat, + ) + + messages_chunk = DATA.get(message.chat.id) + message_schema = MessageFromChatSchema( + id=message.id, + user_id=message.from_user.id, + chat_id=message.chat.id, + text=message.text, + message_time=message.date, + ) + + + if messages_chunk and len(messages_chunk) == MESSAGE_CHANG_SIZE: # TODO в констант. + await some_publisher() + del DATA[message.chat.id] + + if messages_chunk: + DATA[message.chat.id].append(message_schema) + else: + DATA[message.chat.id] = [message_schema] diff --git a/telegram-application/src/core/tg_service/schemas.py b/telegram-application/src/core/tg_service/schemas.py new file mode 100644 index 0000000..287ee27 --- /dev/null +++ b/telegram-application/src/core/tg_service/schemas.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel + + + +class UserFromMessageSchema(BaseModel): + id: int + username: str + first_name: str + last_name: str diff --git a/telegram-application/src/core/tg_service/service.py b/telegram-application/src/core/tg_service/service.py new file mode 100644 index 0000000..bfa619f --- /dev/null +++ b/telegram-application/src/core/tg_service/service.py @@ -0,0 +1,55 @@ +from pyrogram.types.user_and_chats import User, Chat + +from src.core.tg_service.schemas import UserFromMessageSchema +from src.core.database.connect import db_helper +from src.core.redis_helper.redis_connect import redis_client +from src.core.tg_service import crud as tg_crud + + +async def check_user_exists( + user_pyrogram: User, +) -> None: + user_schema = UserFromMessageSchema( + username=user_pyrogram.username, + first_name=user_pyrogram.first_name, + last_name=user_pyrogram.last_name, + id=user_pyrogram.id, + ) + + user_model = await redis_client.get(name=str(user_schema.id)) + if user_model: + return + + async with db_helper.get_async_session() as session: + user_model = await session.get(id=user_model.id) + + if not user_model: + await tg_crud.create_new_user( + session=session, + **user_schema.model_dump() + ) + + await redis_client.set(name=str(user_schema.id), value=True) + + +async def check_chat_exists( + chat_pyrogram: Chat +) -> None: + chat = await redis_client.get(chat_id=str(chat_pyrogram.id)) + + if chat: + return + + async with db_helper.get_async_session() as session: + chat = await session.get(id=chat_pyrogram.id) + + if not chat: + await tg_crud.create_new_chat( + session=session, + id=chat_pyrogram.id, + chat_type=chat_pyrogram.type.value, + title=chat_pyrogram.title, + ) + await redis_client.set(name=str(chat_pyrogram.id), value=True) + + diff --git a/telegram-application/src/core/tg_service/utils.py b/telegram-application/src/core/tg_service/utils.py new file mode 100644 index 0000000..e4fe738 --- /dev/null +++ b/telegram-application/src/core/tg_service/utils.py @@ -0,0 +1,13 @@ +from pyrogram.types import Message +from pyrogram.enums import ChatType + +def check_message_condition( + message: Message, +) -> bool: + conditions = ( + message.chat.type not in [ChatType.PRIVATE, ChatType.BOT], + bool(message.from_user), + bool(message.text), + ) + return all(conditions) + diff --git a/telegram-application/src/main.py b/telegram-application/src/main.py new file mode 100644 index 0000000..d04740c --- /dev/null +++ b/telegram-application/src/main.py @@ -0,0 +1,25 @@ +from pyrogram import Client, filters +from pyrogram.handlers import MessageHandler + +from src.core.tg_service.messages_handler import message_listener +from src.core.rabbitmq.connect import broker + +api_id = 17718565 +api_hash = "72f93973f4227415572f039d4f847082" + +app = Client( + name="advatroniks", + api_id=api_id, + api_hash=api_hash, +) + +app.add_handler(MessageHandler( + callback=message_listener, + filters=filters.all +)) + +# Запуск клиента +if __name__ == "__main__": + async with broker.start(): + async with app.run(): + app.run() \ No newline at end of file