Current project state
This commit is contained in:
442
PROJECT.md
Normal file
442
PROJECT.md
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
# PROJECT_STATE.md
|
||||||
|
|
||||||
|
# Anime Automation Project
|
||||||
|
|
||||||
|
Версия документа: 0.1
|
||||||
|
|
||||||
|
Последнее обновление: 2026-06-27
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 1. Цель проекта
|
||||||
|
|
||||||
|
Разработать полностью автоматизированный pipeline обработки новых аниме-релизов после завершения скачивания через qBittorrent.
|
||||||
|
|
||||||
|
Автоматизация должна работать в локальном экземпляре n8n и выполнять все операции без участия пользователя.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 2. Окружение
|
||||||
|
|
||||||
|
## n8n
|
||||||
|
|
||||||
|
* Version: 2.26.8
|
||||||
|
* Deployment: Docker
|
||||||
|
* Доступ осуществляется по HTTPS через доменное имя.
|
||||||
|
|
||||||
|
## Torrent Client
|
||||||
|
|
||||||
|
* qBittorrent
|
||||||
|
* Загрузка через RSS
|
||||||
|
* После окончания скачивания вызывается Bash Script.
|
||||||
|
* Bash Script отправляет HTTP POST в Webhook n8n.
|
||||||
|
|
||||||
|
## NAS
|
||||||
|
|
||||||
|
* Synology DSM
|
||||||
|
* Доступ только по SSH
|
||||||
|
* Python3 установлен
|
||||||
|
* 7z установлен
|
||||||
|
* crc32 отсутствует
|
||||||
|
* rhash отсутствует
|
||||||
|
* 7zz отсутствует
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 3. Архитектурные решения
|
||||||
|
|
||||||
|
## Решение №1
|
||||||
|
|
||||||
|
Вся бизнес-логика находится в n8n.
|
||||||
|
|
||||||
|
На NAS не создаются дополнительные Python-скрипты.
|
||||||
|
|
||||||
|
Причина:
|
||||||
|
|
||||||
|
* переносимость
|
||||||
|
* отсутствие зависимости от конкретного NAS
|
||||||
|
* простота резервного копирования
|
||||||
|
* вся автоматизация хранится в одном месте
|
||||||
|
|
||||||
|
Статус:
|
||||||
|
|
||||||
|
ПРИНЯТО
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Решение №2
|
||||||
|
|
||||||
|
NAS используется исключительно как:
|
||||||
|
|
||||||
|
* файловое хранилище
|
||||||
|
* SSH endpoint
|
||||||
|
|
||||||
|
Статус:
|
||||||
|
|
||||||
|
ПРИНЯТО
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Решение №3
|
||||||
|
|
||||||
|
Все вычисления выполняются средствами:
|
||||||
|
|
||||||
|
* SSH Node
|
||||||
|
* Code Node
|
||||||
|
* HTTP Request
|
||||||
|
* IF
|
||||||
|
* Merge
|
||||||
|
* Set
|
||||||
|
|
||||||
|
Статус:
|
||||||
|
|
||||||
|
ПРИНЯТО
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Решение №4
|
||||||
|
|
||||||
|
Разработка ведется небольшими шагами.
|
||||||
|
|
||||||
|
Каждый следующий шаг начинается только после проверки предыдущего.
|
||||||
|
|
||||||
|
Статус:
|
||||||
|
|
||||||
|
ПРИНЯТО
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Решение №5
|
||||||
|
|
||||||
|
Если возникает необходимость изменить ранее предложенное решение, обязательно фиксируются:
|
||||||
|
|
||||||
|
* что изменилось;
|
||||||
|
* почему изменилось;
|
||||||
|
* нужно ли переделывать предыдущие шаги.
|
||||||
|
|
||||||
|
Статус:
|
||||||
|
|
||||||
|
ПРИНЯТО
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 4. Правила разработки
|
||||||
|
|
||||||
|
Работа ведется исключительно для n8n 2.26.8.
|
||||||
|
|
||||||
|
Не использовать рекомендации для других версий.
|
||||||
|
|
||||||
|
Перед созданием новой Node необходимо:
|
||||||
|
|
||||||
|
1. Указать тип Node.
|
||||||
|
2. Указать название Node.
|
||||||
|
3. Полностью привести настройки.
|
||||||
|
4. Полностью привести код.
|
||||||
|
5. Объяснить механизм работы.
|
||||||
|
6. Описать ожидаемый результат.
|
||||||
|
7. Описать способ проверки.
|
||||||
|
|
||||||
|
Если синтаксис конкретной Node вызывает сомнение, сначала создается минимальный тест (MRT), затем используется проверенный шаблон.
|
||||||
|
|
||||||
|
Никогда не выдавать предположения за проверенные решения.
|
||||||
|
|
||||||
|
Каждое утверждение должно иметь один из статусов:
|
||||||
|
|
||||||
|
* ФАКТ
|
||||||
|
* ГИПОТЕЗА
|
||||||
|
* РЕКОМЕНДАЦИЯ
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 5. Особенности SSH Node
|
||||||
|
|
||||||
|
Подтверждено экспериментально.
|
||||||
|
|
||||||
|
Command в режиме Expression должен использовать синтаксис:
|
||||||
|
|
||||||
|
{{'команда'}}
|
||||||
|
|
||||||
|
Например:
|
||||||
|
|
||||||
|
{{'echo test'}}
|
||||||
|
|
||||||
|
Preview:
|
||||||
|
|
||||||
|
echo test
|
||||||
|
|
||||||
|
Рабочий пример:
|
||||||
|
|
||||||
|
{{'python3 -c 'print("OK")''}}
|
||||||
|
|
||||||
|
Preview:
|
||||||
|
|
||||||
|
python3 -c 'print("OK")'
|
||||||
|
|
||||||
|
Данный шаблон использовать для всех последующих SSH-команд.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 6. Реализованные этапы
|
||||||
|
|
||||||
|
## ✔ Webhook
|
||||||
|
|
||||||
|
Получает:
|
||||||
|
|
||||||
|
name
|
||||||
|
|
||||||
|
savepath
|
||||||
|
|
||||||
|
hash
|
||||||
|
|
||||||
|
Проверено.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✔ Normalize
|
||||||
|
|
||||||
|
Формирует единый формат данных.
|
||||||
|
|
||||||
|
Результат:
|
||||||
|
|
||||||
|
received_at
|
||||||
|
|
||||||
|
torrent_name
|
||||||
|
|
||||||
|
save_path
|
||||||
|
|
||||||
|
torrent_hash
|
||||||
|
|
||||||
|
Проверено.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✔ Parse Release
|
||||||
|
|
||||||
|
Поддерживается формат релизов SubsPlease.
|
||||||
|
|
||||||
|
Получаются поля:
|
||||||
|
|
||||||
|
group
|
||||||
|
|
||||||
|
title
|
||||||
|
|
||||||
|
episode
|
||||||
|
|
||||||
|
resolution
|
||||||
|
|
||||||
|
crc
|
||||||
|
|
||||||
|
extension
|
||||||
|
|
||||||
|
Проверено.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✔ Check File Exists
|
||||||
|
|
||||||
|
Через SSH проверяется наличие скачанного файла.
|
||||||
|
|
||||||
|
Проверено.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✔ Calculate CRC
|
||||||
|
|
||||||
|
Через SSH и Python3 вычисляется CRC32 скачанного файла.
|
||||||
|
|
||||||
|
Проверено.
|
||||||
|
|
||||||
|
Пример результата:
|
||||||
|
|
||||||
|
8D8395C0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✔ Compare CRC
|
||||||
|
|
||||||
|
Code Node сравнивает:
|
||||||
|
|
||||||
|
CRC из имени релиза
|
||||||
|
|
||||||
|
с
|
||||||
|
|
||||||
|
CRC вычисленным по содержимому файла.
|
||||||
|
|
||||||
|
Результат:
|
||||||
|
|
||||||
|
crc_match = true
|
||||||
|
|
||||||
|
Проверено.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 7. Текущее состояние Workflow
|
||||||
|
|
||||||
|
Webhook
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Normalize
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Parse Release
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Check File Exists
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Calculate CRC
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Compare CRC
|
||||||
|
|
||||||
|
Все перечисленные узлы полностью реализованы и протестированы.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 8. Текущая точка остановки
|
||||||
|
|
||||||
|
Последняя успешно протестированная Node:
|
||||||
|
|
||||||
|
Compare CRC
|
||||||
|
|
||||||
|
Последний подтвержденный результат:
|
||||||
|
|
||||||
|
crc_match = true
|
||||||
|
|
||||||
|
Ошибок нет.
|
||||||
|
|
||||||
|
На этом работа предыдущего чата завершена.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 9. Следующий шаг
|
||||||
|
|
||||||
|
Создать IF Node.
|
||||||
|
|
||||||
|
Название:
|
||||||
|
|
||||||
|
Check CRC
|
||||||
|
|
||||||
|
Условие:
|
||||||
|
|
||||||
|
crc_match == true
|
||||||
|
|
||||||
|
Ветка TRUE:
|
||||||
|
|
||||||
|
Продолжить обработку.
|
||||||
|
|
||||||
|
Ветка FALSE:
|
||||||
|
|
||||||
|
Завершить Workflow.
|
||||||
|
|
||||||
|
(Уведомление об ошибке будет реализовано позднее.)
|
||||||
|
|
||||||
|
До создания IF Node не переходить к интеграции с AniList.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 10. Backlog
|
||||||
|
|
||||||
|
После успешного создания IF Node реализовать:
|
||||||
|
|
||||||
|
1.
|
||||||
|
|
||||||
|
Интеграцию с AniList.
|
||||||
|
|
||||||
|
Получить:
|
||||||
|
|
||||||
|
* ID
|
||||||
|
* название
|
||||||
|
* описание
|
||||||
|
* жанры
|
||||||
|
* постер
|
||||||
|
* баннер
|
||||||
|
|
||||||
|
2.
|
||||||
|
|
||||||
|
Спроектировать структуру медиатеки.
|
||||||
|
|
||||||
|
Максимальная совместимость с Kodi.
|
||||||
|
|
||||||
|
3.
|
||||||
|
|
||||||
|
Создать каталоги.
|
||||||
|
|
||||||
|
4.
|
||||||
|
|
||||||
|
Создать hardlink.
|
||||||
|
|
||||||
|
5.
|
||||||
|
|
||||||
|
Создать metadata.
|
||||||
|
|
||||||
|
На первом этапе допускается хранение в виде отдельных файлов.
|
||||||
|
|
||||||
|
Позже перейти к полноценным NFO.
|
||||||
|
|
||||||
|
6.
|
||||||
|
|
||||||
|
Настроить SMTP.
|
||||||
|
|
||||||
|
7.
|
||||||
|
|
||||||
|
Отправлять итоговое уведомление.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 11. Журнал архитектурных решений
|
||||||
|
|
||||||
|
2026-06-27
|
||||||
|
|
||||||
|
Отказались от варианта размещения Python-скриптов на NAS.
|
||||||
|
|
||||||
|
Причина:
|
||||||
|
|
||||||
|
Вся логика должна находиться в n8n.
|
||||||
|
|
||||||
|
NAS не должен содержать бизнес-логику.
|
||||||
|
|
||||||
|
Статус:
|
||||||
|
|
||||||
|
ПРИНЯТО.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
2026-06-27
|
||||||
|
|
||||||
|
Для проверки целостности релизов SubsPlease принято использовать CRC, содержащийся в имени файла.
|
||||||
|
|
||||||
|
Сравнение производится с CRC, вычисленным по содержимому файла.
|
||||||
|
|
||||||
|
Получение CRC с сайта релизной группы признано избыточным.
|
||||||
|
|
||||||
|
Статус:
|
||||||
|
|
||||||
|
ПРИНЯТО.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 12. Правило продолжения проекта
|
||||||
|
|
||||||
|
Каждый новый чат начинается с чтения данного документа.
|
||||||
|
|
||||||
|
После этого определяется:
|
||||||
|
|
||||||
|
1.
|
||||||
|
|
||||||
|
Какой этап завершен.
|
||||||
|
|
||||||
|
2.
|
||||||
|
|
||||||
|
Какой этап является следующим.
|
||||||
|
|
||||||
|
Только после этого предлагаются новые Node.
|
||||||
|
|
||||||
|
После завершения каждого этапа данный документ обновляется.
|
||||||
|
|
||||||
|
Этот документ является единственным источником актуального состояния проекта.
|
||||||
Reference in New Issue
Block a user