- Rust 94.2%
- JavaScript 3.7%
- Nix 2.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
`verification_code` в url_matches ловил сам authorize_url (там redirect_uri=…/verification_code), поэтому wait срабатывал мгновенно на стартовой странице — вход падал с «в URL нет access_token». Сузил до access_token= / ?code= / якорь ^…/verification_code; источник токена — сматченный url (фрагмент redirect), eval location.href как фолбэк. Co-Authored-By: Eva |
||
| crates/eda | ||
| spec | ||
| .env.example | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
eva-eda
Модуль Яндекс.Еды для ядра Евы (на eva-sdk, как telegram-bridge): поиск
заведений, меню, сбор корзины, оформление заказа и трекинг статуса — от лица
аккаунта Господина. Отдельный процесс: отдаёт инструменты ядру по UDS, а туры
ведёт через HTTP API ядра.
Реверс протокола и дизайн auth — в spec/. Артефакты декомпила
(jadx-out/, apktool-out/, xapk/, libs/) в git не хранятся.
Auth: KV-стор + module-driven вход
Токен живёт в per-module KV-сторе ядра (Kernel::store("eda"), ключ
token) — сериализованным JSON'ом (access_token, опц. token_type,
expires_at, refresh_token, scope). На каждый вызов модуль читает его из
стора. Если токена нет, он на пороге истечения (expires_at) или пришёл
401, модуль добывает его заново и кладёт обратно в стор:
- OAuth-refresh — если у токена есть
refresh_tokenИ заданыeda.client_id/client_secret/token_url(POST token_urlgrant_type=refresh_token). У implicit-флоу Яндекса (response_type=token) refresh_token обычно нет — тогда сразу шаг 2. - Переоткрыть вход через webview машины Господина: открыть
eda.authorize_url(ephemeral:false— переиспользует уже залогиненный в Яндексе аккаунт, куки на месте → быстро), дождаться редиректа (url_matches: access_token=|verification_code|[?&]code=), прочитатьlocation.href, распарситьaccess_token/expires_in/refresh_tokenиз фрагмента/query.
При 401 токен добывается заново, переигрывается /4.0/startup, запрос
повторяется один раз. Схему Authorization: OAuth <token> клиент ставит сам.
Токен нигде не логируется.
Инструменты
| Инструмент | Что | Эндпоинт |
|---|---|---|
eda_profile |
профиль + проверка токена | GET api/v1/user/profile |
eda_addresses |
сохранённые адреса доставки | GET api/v3/user/addresses |
eda_restaurants |
заведения по координатам (+фильтр) | POST api/v2/catalog |
eda_menu |
меню заведения по slug | GET api/v2/menu/retrieve/{slug} |
eda_cart_add |
положить позиции в корзину | POST api/v1/cart/add_bulk |
eda_cart |
текущая корзина: состав, сумма, адрес | GET api/v2/cart |
eda_cart_clear |
очистить корзину | POST api/v1/cart/change_place |
eda_checkout |
оформить заказ (тратит деньги) | POST api/v2/cart/go-checkout |
eda_orders |
статус заказов | GET api/v1/orders[/{id}] |
Оформление — только с подтверждением
eda_checkout тратит реальные деньги и необратим. Он требует confirm=true;
без него возвращает текущую корзину и отказ. Порядок: собрать корзину → показать
состав + сумму + адрес → получить явное «да» Господина → eda_checkout(confirm=true).
Конфигурация
Каркас — фреймворк eva: конфиг читается из --config-файлов (YAML/JSON/TOML),
секция eda. Env перекрывают файлы: EVA_ + путь через __
(Env::prefixed("EVA_").split("__")), напр. EVA_EDA__CLIENT_SECRET →
eda.client_secret.
Ключ секции eda |
Назначение |
|---|---|
socket |
UDS с инструментами (дефолт /run/eva-mcp/eda.sock) |
kernel_url |
база API ядра (дефолт http://127.0.0.1:8090) — KV-стор и webview |
authorize_url |
страница авторизации для webview-входа; пусто — автовход недоступен |
lat / lon |
координаты доставки по умолчанию |
lang |
язык ответов API (дефолт ru) |
device_id |
стабильный device id (иначе выводится из хоста) |
client_id / client_secret / token_url |
опц. — OAuth-refresh (все три) |
client_secret — секрет: не клади в несекретный --config/nix-settings, а
задавай через env (EVA_EDA__CLIENT_SECRET, systemd environmentFiles) или
секретный --config в extraConfigFiles. Хост API переопределяется env
YANDEX_EDA_API_HOST (дефолт — прод authproxy). Пример конфига —
.env.example (env-форма для systemd EnvironmentFile).
Сборка и запуск
nix develop -c cargo build # dev-сборка в devShell
nix build .#eva-eda # пакет (crane, без ручных хэшей)
./result/bin/eva-eda --config eda.yaml # запуск с конфигом
Ядро цепляется к сокету само, если тот лежит в modules.socket_dir ядра или
объявлен в modules.servers.
Nix
flake.nix собран на eva.lib.mkServiceFlake (crane): даёт packages.eva-eda,
devShells.default и nixosModules.default (services.eva-eda). Git-депы
(eva, eva-sdk) crane вендорит из Cargo.lock сам — ручных outputHashes
нет; смена rev SDK хэш-танца не требует. Секреты в модуле — через
services.eva-eda.environmentFiles (EVA_EDA__CLIENT_SECRET=...) или
extraConfigFiles.
Статус протокола
Пути эндпоинтов и заголовки восстановлены из декомпила ru.foodfox.client
v26.33.0 (см. spec/20-yandex-eda-api.md).
Точные тела запросов (add_bulk, go-checkout, change_place, catalog)
спека велит доснять живым трафиком (mitmproxy на один прогон) — в коде они
best-effort и помечены комментарием; парсинг ответов терпим к расхождению схемы.
При первом реальном заказе тела стоит сверить и поправить client.rs/tools.rs.