Стоит сказать сразу: это, по сути, приложение, спрятанное в Discord-бота.
Так вот, здесь будет рассказываться, для чего он, чем вдохновлён и почему здесь вообще чистая архитектура и не оверинжиниринг ли тут.
Это не обучающий проект и он не претендует на идеальность. Если вы найдёте серьёзные огрехи (которые не указаны ниже) - прошу
Если вы знаете меня и решили просто поглядеть репозитории - пожалуйста, читайте, возможно вы будете даже знакомы с проектом.
Если вы хотите вычленить отсюда полезную информацию, то этот README не совсем будет вам релевантен (но всё же полезная информация будет, не переживайте). Здесь есть немного технической информации, как эту махину запустить, немного обо всём и вообще. Возможно, я добавлю небольшую документацию по проекту, однако он локальный и со специфичной тематикой, что я просто понятия не имею, кому он нужен кроме меня. Так что, это не README в привычном понимании. Прошу принять во внимание.
TL;DR: это локальный и специфичный проект, так что README здесь скорее вводный, чем технически исчерпывающий.
Для реализации механик моего вымышленного мира. В дискорде руками было бы муторно и скучно это делать, а бот это всё автоматизировал. Плюсом, снимает бесячую ручную модерацию некоторого специфичного контента, который было бы противно чистить руками.
Да, для локального и специфичного бота можно было обойтись и чем-нибудь попроще. Такой выбор был осознанным.
Итак, представьте: вы сели в самолёт, но вспомнили, что вы пилот. Ваши действия?
Открыть src/marionette/ и увидеть:
application/usecases/- это то, чем бот жонглирует в командах или каких-либо штуках, где нужна рука пользователяapplication/protocols/- протоколы репозиториев. Просто описание. Не более.domain/policies- некоторые бизнес-правила, которые говорят, как именно и правильно обрабатывать некоторые сценарииdomain/services/rating_service.py- это сердце рейтинговой системы и в целом того мира, для которого приложение создавалосьinfrastructure/repositories/- так сказать удочки, которые достают всю нужную информацию из БД. Реализованы на базеprotocols/presentation/discord/- то, ради чего вы сюда, скорее всего, заглянули.presentation/discord/presenters- удобная и красивая прослойка для сообщений, эмбедов и прочей Discord-эпопеиtests/*- думаю, не нуждается в объяснении
Вкатывать в тему игры не буду, позже здесь появится дискорд сервер - там сможете сами всё потыкать. Но из базового:
- Вход/выход из локации
- Постинг новостей
- Папарацци
- Система рейтинга
- Автомодерация нежелательного non-RP контента в RP-чатах
- Онбординг новых пользователей
Бот создавался для локального и весьма специфичного комьюнити, а именно: ролевая игра по мотивам японского шоу-бизнеса, приукрашенная аниме и мангой Oshi no Ko
Немного детская и наивная идея, однако она мне понравилась. Если вы не любитель такого - можете спокойно пропускать данный этап README.
Рейтинговая система была вдохновлена частично механикой из MLBB (Mobile Legends: Bang Bang), а именно, ежесезонный сброс рейтинга.
Придумка с увеличением сложности набора рейтинга в зависимости от него самого - уже моя.
Вдохновлено эпизодом из OnK, где Кану выследил папарацци.
Ну, собственно, новости... Они создают живую атмосферу, на мой взгляд.
Вот это я делал просто потому что захотел и, вроде как, это даже снизит порог входа в РП.
Здесь Python 3.14, остальное читайте в pyproject.toml.
Чистая архитектура - да, отчасти оверинжиниринг, но это в основном учебный проект и с ним я понял, как правильнее писать архитектуру и в каком направлении в целом думать. Советую прочитать про coupling и cohesion, если говорить об архитектуре.
Но с Бобом Мартином согласен в том, что хорошая архитектура должна быть легко тестируема.
Здесь на борту PostgreSQL, Redis и всеми (не)любимая SQLAlchemy. Миграции работают через alembic, драйвер - psycopg.
Пакетный менеджер: uv.
Контейнеризация через Docker.
Почему такой стек? Да потому что захотелось. Постгре круто, редис вайб, алхимия потому что позволяет проект, алембик потому что удобно, а драйвер - просто стало интересно, что это за покемон такой. До написания марионетки я не знал о нём. Как оказалось, asyncpg эффективнее и практически везде лучше psycopg, так что делайте выводы.
├── src # src-layout
│ └── marionette
│ ├── application/ # Слой приложения, тут лежат юзкейсы и происходит всё то, что должно делать приложение
│ ├── bootstrap/ # Точка входа + DI
│ ├── domain/ # Бизнес-логика и бизнес-правила, а также сущности
│ ├── infrastructure/ # Взамодействие с внешним миром
│ ├── presentation/ # Показ приложения внешнему мируДля начала:
python3 -m pip install uvПеред запуском отредактируйте .env
Ручной прикол:
uv pip install -e .
uv lock
uv run python -m marionette
# но тогда у вас не поднимутся метрики, так что делайте выводыКонтейнером:
make up
# а рестартить можно через
make restart
# Доступные флаги: DETACH (по дефолту 1), BUILD (по дефолту 0)Warning
Пожалуйста, учитывайте своё окружение. Эти команды подстроены под моё окружение. У вас могут отличаться версия Docker, версия Docker Compose.
На хабре есть статья о заблуждениях в чистой архитектуре, вот она
И что я могу выделить у себя... у меня нет интеракторов. Я, честно, не совсем понял статью. Поначалу говорится, что по Бобу Мартину Interactors - просто другое название UseCase'ов, а ниже пишется, что есть интеракторы для слоя юзкейсов. Ну и я решил сильно не париться и оставил юзкейсы как есть. У меня они выступают в роли обычных оркестраторов с небольшими заделами бизнес-логики, всё совсем строго я не разделял
В домене у меня отступление от Боба Мартина конкретное - в entities/ у меня лежат SQLAlchemy модели, что отходит от канона книги. Но я пошёл на этот компромисс осознанно (ну... мягко объяснили), что с relationship'ами лучше, проще и быстрее сделать именно так. В целом, согласен - так и вправду удобнее. Но переезжать с алхимии будет труднее, согласен. Но не прям уж чтобы... Это также рассчитано и с учётом того, как далеко будет разрататься кодовая база, а её предел я знаю заранее.
Вот, надеюсь лишних претензий не будет. Углубляться далеко, что именно удобнее и почему не стану. Всё равно содержание этого заголовка никто не прочитает.
Note
Окружение, в котором всё создавалось и тестировалось:
Python 3.14.2 (main, Jan 10 2026, 19:46:42) [GCC 15.2.1 20260103] on linux
Docker: Docker version 29.1.4, build 0e6fee6c52
Docker Compose version 5.0.1
uv 0.9.26