|
1 | | - |
2 | | - |
3 | | -# Link Tracker |
| 1 | +# 📌 Link Tracker |
4 | 2 |
|
5 | 3 | ---- |
6 | 4 |
|
7 | 5 | Чтобы бот заработал нужно в переменные среды загрузить TELEGRAM_TOKEN |
8 | 6 |
|
9 | 7 | ---- |
10 | 8 |
|
11 | | -<!-- этот файл можно и нужно менять --> |
12 | | - |
13 | | -Проект сделан в рамках курса Академия Бэкенда. |
| 9 | +## 📝 Описание проекта |
14 | 10 |
|
15 | 11 | Приложение для отслеживания обновлений контента по ссылкам. |
16 | 12 | При появлении новых событий отправляется уведомление в Telegram. |
|
21 | 17 | * Bot |
22 | 18 | * Scrapper |
23 | 19 |
|
24 | | -Для работы требуется БД `PostgreSQL`. Присутствует опциональная зависимость на `Kafka`. |
| 20 | +Для работы требуется БД `PostgreSQL`, `Redis`, `Kafka`. |
25 | 21 |
|
26 | 22 | Для дополнительной справки: [HELP.md](./HELP.md) |
| 23 | + |
| 24 | +--- |
| 25 | + |
| 26 | +## 🤖 Бот |
| 27 | + |
| 28 | +### 📌 Функционал |
| 29 | + |
| 30 | +Бот поддерживает следующие команды: |
| 31 | + |
| 32 | +- [**`/help`**]() — список всех доступных команд. |
| 33 | +- [**`/start`**]() — регистрация пользователя. |
| 34 | +- [**`/stop`**]() — удаление всех данных о чате (ID чата, отслеживаемые ссылки и т. д.). |
| 35 | +- [**`/track`**]() — добавление ссылки для отслеживания |
| 36 | +- [**`/untrack`**]() — удаление ссылки из списка отслеживаемых. |
| 37 | +- [**`/list`**]() — получение списка всех отслеживаемых ссылок. |
| 38 | +- [**`/tag`**]() — для просмотра всех тегов (/tag) и ссылок под конкретным тегом (/tag < tag >) |
| 39 | + |
| 40 | +### 🔄 Взаимодействие со Scrapper |
| 41 | + |
| 42 | +Бот общается со Scrapper API через: |
| 43 | +- [**`ChatClient`**]() — регистрация и удаление чатов. |
| 44 | +- [**`LinkClient`**]() — управление ссылками (добавление, удаление, получение списка). |
| 45 | +- [**`TagClient`**]() — для получения списка тегов и ссылок по тегу. |
| 46 | + |
| 47 | +Scrapper API работает по OpenAPI-контракту. В случае ошибок ошибки логируются, корректную обработку ошибок и пересылку сообщений в чат выполняет [`ErrorHandler`](). |
| 48 | + |
| 49 | +### 📩 Получение обновлений |
| 50 | + |
| 51 | +- Бот получает обновления о ссылках через [`UpdateController`]() по HTTP либо через [`KafkaUpdateListener`]() по Kafka. |
| 52 | +- Scrapper отправляет данные по OpenAPI-контракту. |
| 53 | +- Обновления рассылаются чатам через [`UpdateService`](). |
| 54 | + |
| 55 | +### 📜 Дополнительно |
| 56 | + |
| 57 | +- Бот поддерживает встроенное [**меню команд**]() в Telegram. |
| 58 | + |
| 59 | +### 🧠 Кеширование |
| 60 | + |
| 61 | +Бот кеширует ответы для следующих команд: |
| 62 | +- /tag |
| 63 | +- /tag <tag> |
| 64 | +- /list |
| 65 | + |
| 66 | +🔄 Кеш автоматически сбрасывается в следующих случаях: |
| 67 | +- При добавлении или удалении ссылки (/track, /untrack) |
| 68 | +- При удалении чата (/stop) |
| 69 | + |
| 70 | +При вызове команд бот сначала проверяет наличие ответа в кеше. Если данные найдены — используется кеш. В противном случае происходит обращение к Scrapper API, и результат сохраняется в кеш. |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +## 🗂️ Scrapper |
| 75 | + |
| 76 | +### 📌 Функционал |
| 77 | + |
| 78 | +Scrapper обрабатывает запросы от бота: |
| 79 | +- **Работа с чатами** через [`ChatController`](). |
| 80 | +- **Работа с ссылками** через [`LinkController`](). |
| 81 | +- **Работа с тегами** через [`TagController`](). |
| 82 | + |
| 83 | +Все контроллеры работают по OpenAPI-контракту. |
| 84 | + |
| 85 | +### 🔄 Получение обновлений |
| 86 | + |
| 87 | +- [**`UpdateScheduler`**](). |
| 88 | +- **📡 Источники данных:** |
| 89 | + - GitHub — через [`GitHubClient`]() |
| 90 | + - Stack Overflow — через [`StackOverflowClient`]() |
| 91 | +- **⚙️ Обработка полученных данных** |
| 92 | + 1. Запрос обновлений |
| 93 | + - Для каждого URL запрашивается обновление через API |
| 94 | + 2. Фильтрация обновлений |
| 95 | + - Определяются подписанные пользователи (чаты), которые отслеживают данный URL. |
| 96 | + - Для каждого пользователя применяется его список фильтров: |
| 97 | + 1. Ключевые фильтры — фильтрация по ключевым словам (issue, commit и т.д). |
| 98 | + 2. Анти-фильтры по пользователям — если указано user=username, то обновления от этого пользователя игнорируются. |
| 99 | + 3. Парсинг ответа |
| 100 | + - Полученный JSON-ответ анализируется, извлекаются значения, соответствующие фильтрам. |
| 101 | + 4. Проверка актуальности |
| 102 | + - Обновление считается релевантным, если оно произошло после последнего запуска шедулера. |
| 103 | + 5. Формирование уведомлений |
| 104 | + - Отобранные обновления, соответствующие фильтрам, отправляются пользователям либо через HTTP, либо через Kafka. |
| 105 | +- **⚙️ Обработка батчей и многопоточность** |
| 106 | + - Ссылки на обновления запрашиваются партиями (batch) заданного размера. Каждый батч делится между потоками. Количество потоков настраивается через конфигурацию. |
| 107 | + |
| 108 | +## 📦 Хранение данных |
| 109 | + |
| 110 | +Для хранения данных используются **четыре основные таблицы** и **три вспомогательные таблицы** для связи. |
| 111 | + |
| 112 | +### 📌 Основные таблицы |
| 113 | + |
| 114 | +- `chats` — таблица чатов. |
| 115 | +- `links` — таблица ссылок. |
| 116 | +- `tags` — таблица тегов. |
| 117 | +- `filters` — таблица фильтров. |
| 118 | + |
| 119 | +### 🔗 Связующие таблицы |
| 120 | + |
| 121 | +Связи между чатами, ссылками, тегами и фильтрами реализованы через **промежуточные таблицы**: |
| 122 | + |
| 123 | +- `chat_links` — связь между чатами и ссылками. |
| 124 | +- `chat_link_tags` — связь между ссылками и тегами в контексте чата. |
| 125 | +- `chat_link_filters` — связь между ссылками и фильтрами в контексте чата. |
| 126 | + |
| 127 | +💡 **Один чат может отслеживать несколько ссылок, а одна ссылка может быть отслеживаемой несколькими чатами.** |
| 128 | +📌 **Каждая ссылка может иметь несколько тегов и фильтров в рамках одного чата.** |
| 129 | + |
| 130 | +### 🛠 Способы работы с базой данных: |
| 131 | + |
| 132 | +- **SQL** (`JdbcTemplate`, `SqlRepository`). |
| 133 | +- **ORM** (`Hibernate`, `OrmRepository`). |
| 134 | + Оба репозитория (`SqlRepository` и `OrmRepository`) наследуются от `DbRepository` и работают одинаково. |
| 135 | + Выбор зависит от **настроек** (`database.access-type`). |
| 136 | + |
| 137 | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 138 | + |
| 139 | +## 🚀 Запуск проекта |
| 140 | + |
| 141 | +### 🔄 Клонирование репозитория |
| 142 | + |
| 143 | +```bash |
| 144 | + |
| 145 | +``` |
| 146 | + |
| 147 | +### 🏗️ Сборка |
| 148 | + |
| 149 | +```bash |
| 150 | + |
| 151 | +``` |
| 152 | + |
| 153 | +### ▶️ Запуск |
| 154 | + |
| 155 | +#### 1️⃣ Запуск базы |
| 156 | + |
| 157 | +```bash |
| 158 | + |
| 159 | +``` |
| 160 | + |
| 161 | +#### 2️⃣ Запуск миграции |
| 162 | + |
| 163 | +```bash |
| 164 | + |
| 165 | +``` |
| 166 | + |
| 167 | +#### 3️⃣ Запуск redis |
| 168 | + |
| 169 | +```bash |
| 170 | + |
| 171 | +``` |
| 172 | + |
| 173 | +#### 4️⃣ Запуск zookeeper |
| 174 | + |
| 175 | +```bash |
| 176 | + |
| 177 | +``` |
| 178 | + |
| 179 | +#### 5️⃣ Запуск kafka |
| 180 | + |
| 181 | +```bash |
| 182 | + |
| 183 | +``` |
| 184 | + |
| 185 | +#### 6️⃣ Запуск скраппер |
| 186 | + |
| 187 | +```bash |
| 188 | + |
| 189 | +``` |
| 190 | + |
| 191 | +#### 7️⃣ Запуск бота |
| 192 | + |
| 193 | +```bash |
| 194 | + |
| 195 | +``` |
| 196 | + |
0 commit comments