Skip to content

Feat/unified grizzly tool - #4

Open
kurosaki-sol wants to merge 10 commits into
ErwannCharlier:mainfrom
kurosaki-sol:feat/unified-grizzly-tool
Open

Feat/unified grizzly tool#4
kurosaki-sol wants to merge 10 commits into
ErwannCharlier:mainfrom
kurosaki-sol:feat/unified-grizzly-tool

Conversation

@kurosaki-sol

Copy link
Copy Markdown

Auto-load .env - no more manual set

Added good providers for turkey and the "exceptProviders" for the bad ones avoiding you to loose your time.

Restructure the single ntfy-based bot.py into a small grizzly/ package
(config, api, notify, bot, __main__) and add the SMS-watch phase.

- Unified flow: acquire a number, then watch it for the SMS code in one run.
  `python -m grizzly watch <id> ...` watches already-owned activations only.
- Notifications: pluggable ntfy and/or Discord backends (at least one required;
  both fire if both are configured).
- Hard single-number guarantee: numbers won beyond MAX_ACQUISITIONS by a
  concurrency burst are cancelled (setStatus=8) and refunded.
- Robust workers: fatal responses (BAD_KEY, NO_BALANCE, WRONG_MAX_PRICE) stop
  acquisition; network/HTTP/429 errors back the whole pool off (honours Retry-After).
- Tests: stdlib unittest for parsing, fatal detection, notifier selection, and
  the keep/cancel decision.
- Update Dockerfile (python -m grizzly), .env.example, and README.
- Cancel failure no longer reports a false "refunded": on setStatus(8) error,
  notify "cancel FAILED / manual cancellation needed" (urgent) and stop, instead
  of the success message — restores the hard single-number guarantee.
- Rate-limit the watch-phase getStatus polls (shared RateLimiter) so
  MAX_ACQUISITIONS > 1 / unlimited cannot burst past MAX_REQUESTS_PER_SECOND.
- Distinguish a requested shutdown from a watch-deadline timeout in the watch
  loop's exit notification.
- run() returns exit code 1 when acquisition stops on a fatal response
  (BAD_KEY / NO_BALANCE / WRONG_MAX_PRICE) with nothing kept (Acquirer.fatal).
- notify: aggregate backend results with any([...]) for readability.
- README: footnote marking acquire-only config vs the watch subcommand.
- tests: cover the cancel success/failure paths through _poll_once.
Add a tiny stdlib .env loader (no python-dotenv dependency) called at startup.
It reads KEY=VALUE lines from .env in the working directory without overriding
variables already set in the environment, so explicit env vars and Docker's
env_file still take precedence. GRIZZLY_ENV_FILE overrides the path.

- config.load_dotenv() + call it first in __main__.main().
- README: drop the `set -a && source .env` step, document auto-load.
- tests: load_dotenv (values/comments/export/quotes, no-override, missing file).
Mirror PROVIDER_IDS: read EXCEPT_PROVIDER_IDS from the environment and add it as
`exceptProviderIds` to the getNumber query when set (omitted when empty).

- config: except_provider_ids field, from_env wiring, and params.
- .env.example + README documented.
- tests: params include/omit provider fields.
The startup log referenced cfg.except_providers_ids (wrong plural), which would
raise AttributeError at the start of run(), and joined two format-string
literals without a space. Use cfg.except_provider_ids and add the missing space.

- Add a run() startup test (workers=0 + fake notifier) that exercises the log
  line, catching this class of error without network or threads.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant