Marionette
Бот-движок для ролевой платформы по мотивам японского шоу-бизнеса, вдохновлённой "Oshi no Ko".
Install / Use
/learn @MagM1go/MarionetteREADME
HIKARI // Марионетка
Стоит сказать сразу: это, по сути, приложение, спрятанное в 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/*- думаю, не нуждается в объяснении
Окей, а что умеет как Discord-бот?
Вкатывать в тему игры не буду, позже здесь появится дискорд сервер - там сможете сами всё потыкать. Но из базового:
- Вход/выход из локации
- Постинг новостей
- Папарацци
- Система рейтинга
- Автомодерация нежелательного 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
Related Skills
node-connect
349.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
349.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
349.0kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
