grabcli-service
A service-shaped Grab (food delivery) client over grabcli's library crates, for a server or a bot that keeps many people's Grab accounts in its own storage.
The grab binary keeps one account in files; this crate keeps none. It
gives an embedder:
api: plain, serde-able types (Merchant,Menu,Cart,Quote,Placed,Tracked), the per-accountGrabClient(search, menu, cart, quote, place order, track, refresh), theLoginDriver, theGrabBackendthat makes both, andmoney(₱1,234.50).SessionSlot: the seam to your storage. A session is opaque JSON (grabcli'sSession), read and saved only through the slot; the client's silent refreshes save there too.MemorySlotis an in-memory one.real: the backend overgrabcli-coreandgrabfood.fake: a backend with no network and made-up merchants, for tests and local development (a phone ending in1is approved in the app, one ending in9fails a step-up, any other gets the code123456).login: many phone logins at once (Logins), each on its own thread, bound to the person who started it, one at a time per account, with a per-account code-send budget (60 s apart, 3 an hour by default). A connected account'sdisplay_nameis grabcli's masked phone (+1••••••••00): it shows the number's last two digits, so treat it as personal data where you display or log it.text: the answers as plain text, for a chat reply or a model.
Nothing is printed or read from disk or the environment; diagnostics go to an
optional Log hook, and phones and codes stay in Secrets that never print.
A login's failure message has its phone redacted, and the Debug of
Step, LoggedIn and MemorySlot never shows a session.
Example
use Arc;
use ;
# async
See examples/fake_order.rs
(cargo run -p grabcli-service --example fake_order).
Safety
The real backend keeps grabcli's gates: orders go through only with
allow_ordering = true in the grabcli_core::Config passed to Real::new,
and only against a quote id that matches a fresh re-quote. Never retry
place_order (Grab's submit has no idempotency key); check track instead.
The quote and order path never reads the browse cache.
See the root README's disclaimer.