Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 177 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
![Build](https://github.com/central-university-dev/backend-academy-2025-spring-template/actions/workflows/build.yaml/badge.svg)

# Link Tracker
# 📌 Link Tracker

----

Чтобы бот заработал нужно в переменные среды загрузить TELEGRAM_TOKEN

----

<!-- этот файл можно и нужно менять -->

Проект сделан в рамках курса Академия Бэкенда.
## 📝 Описание проекта

Приложение для отслеживания обновлений контента по ссылкам.
При появлении новых событий отправляется уведомление в Telegram.
Expand All @@ -21,6 +17,180 @@
* Bot
* Scrapper

Для работы требуется БД `PostgreSQL`. Присутствует опциональная зависимость на `Kafka`.
Для работы требуется БД `PostgreSQL`, `Redis`, `Kafka`.

Для дополнительной справки: [HELP.md](./HELP.md)

---

## 🤖 Бот

### 📌 Функционал

Бот поддерживает следующие команды:

- [**`/help`**]() — список всех доступных команд.
- [**`/start`**]() — регистрация пользователя.
- [**`/stop`**]() — удаление всех данных о чате (ID чата, отслеживаемые ссылки и т. д.).
- [**`/track`**]() — добавление ссылки для отслеживания
- [**`/untrack`**]() — удаление ссылки из списка отслеживаемых.
- [**`/list`**]() — получение списка всех отслеживаемых ссылок.
- [**`/tag`**]() — для просмотра всех тегов (/tag) и ссылок под конкретным тегом (/tag < tag >)

### 🔄 Взаимодействие со Scrapper

Бот общается со Scrapper API через:
- [**`ChatClient`**]() — регистрация и удаление чатов.
- [**`LinkClient`**]() — управление ссылками (добавление, удаление, получение списка).
- [**`TagClient`**]() — для получения списка тегов и ссылок по тегу.

Scrapper API работает по OpenAPI-контракту. В случае ошибок ошибки логируются, корректную обработку ошибок и пересылку сообщений в чат выполняет [`ErrorHandler`]().

### 📩 Получение обновлений

- Бот получает обновления о ссылках через [`UpdateController`]() по HTTP либо через [`KafkaUpdateListener`]() по Kafka.
- Scrapper отправляет данные по OpenAPI-контракту.
- Обновления рассылаются чатам через [`UpdateService`]().

### 📜 Дополнительно

- Бот поддерживает встроенное [**меню команд**]() в Telegram.

### 🧠 Кеширование

Бот кеширует ответы для следующих команд:
- /tag
- /tag <tag>
- /list

🔄 Кеш автоматически сбрасывается в следующих случаях:
- При добавлении или удалении ссылки (/track, /untrack)
- При удалении чата (/stop)

При вызове команд бот сначала проверяет наличие ответа в кеше. Если данные найдены — используется кеш. В противном случае происходит обращение к Scrapper API, и результат сохраняется в кеш.

---

## 🗂️ Scrapper

### 📌 Функционал

Scrapper обрабатывает запросы от бота:
- **Работа с чатами** через [`ChatController`]().
- **Работа с ссылками** через [`LinkController`]().
- **Работа с тегами** через [`TagController`]().

Все контроллеры работают по OpenAPI-контракту.

### 🔄 Получение обновлений

- [**`UpdateScheduler`**]().
- **📡 Источники данных:**
- GitHub — через [`GitHubClient`]()
- Stack Overflow — через [`StackOverflowClient`]()
- **⚙️ Обработка полученных данных**
1. Запрос обновлений
- Для каждого URL запрашивается обновление через API
2. Фильтрация обновлений
- Определяются подписанные пользователи (чаты), которые отслеживают данный URL.
- Для каждого пользователя применяется его список фильтров:
1. Ключевые фильтры — фильтрация по ключевым словам (issue, commit и т.д).
2. Анти-фильтры по пользователям — если указано user=username, то обновления от этого пользователя игнорируются.
3. Парсинг ответа
- Полученный JSON-ответ анализируется, извлекаются значения, соответствующие фильтрам.
4. Проверка актуальности
- Обновление считается релевантным, если оно произошло после последнего запуска шедулера.
5. Формирование уведомлений
- Отобранные обновления, соответствующие фильтрам, отправляются пользователям либо через HTTP, либо через Kafka.
- **⚙️ Обработка батчей и многопоточность**
- Ссылки на обновления запрашиваются партиями (batch) заданного размера. Каждый батч делится между потоками. Количество потоков настраивается через конфигурацию.

## 📦 Хранение данных

Для хранения данных используются **четыре основные таблицы** и **три вспомогательные таблицы** для связи.

### 📌 Основные таблицы

- `chats` — таблица чатов.
- `links` — таблица ссылок.
- `tags` — таблица тегов.
- `filters` — таблица фильтров.

### 🔗 Связующие таблицы

Связи между чатами, ссылками, тегами и фильтрами реализованы через **промежуточные таблицы**:

- `chat_links` — связь между чатами и ссылками.
- `chat_link_tags` — связь между ссылками и тегами в контексте чата.
- `chat_link_filters` — связь между ссылками и фильтрами в контексте чата.

💡 **Один чат может отслеживать несколько ссылок, а одна ссылка может быть отслеживаемой несколькими чатами.**
📌 **Каждая ссылка может иметь несколько тегов и фильтров в рамках одного чата.**

### 🛠 Способы работы с базой данных:

- **SQL** (`JdbcTemplate`, `SqlRepository`).
- **ORM** (`Hibernate`, `OrmRepository`).
Оба репозитория (`SqlRepository` и `OrmRepository`) наследуются от `DbRepository` и работают одинаково.
Выбор зависит от **настроек** (`database.access-type`).

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## 🚀 Запуск проекта

### 🔄 Клонирование репозитория

```bash

```

### 🏗️ Сборка

```bash

```

### ▶️ Запуск

#### 1️⃣ Запуск базы

```bash

```

#### 2️⃣ Запуск миграции

```bash

```

#### 3️⃣ Запуск redis

```bash

```

#### 4️⃣ Запуск zookeeper

```bash

```

#### 5️⃣ Запуск kafka

```bash

```

#### 6️⃣ Запуск скраппер

```bash

```

#### 7️⃣ Запуск бота

```bash

```

Loading