A CLI tool to monitor and claim rewards from the Octopus Energy Octoplus partner program.
main.go: Thin entrypoint that delegates to the CLI package.cli/: Cobra/Viper command handling, structured logging, and user-facing output.lib/client/: Octopus client implementation (one method per file).lib/operations/: GraphQL operation requests and operation-specific types.sanitize_har.sh, fetch_js.sh: HAR analysis helpers.We have developed a robust shell script sanitize_har.sh to prepare HAR files for analysis.
octopus.energy).Authorization headers, Cookie values, and POST bodies to protect sensitive session data.Analyzed the Octopus GraphQL schema to identify key operations:
https://api.backend.octopus.energy/v1/graphql/getOctoplusRewards: Retrieves existing voucher codes and history.getOctoplusOfferBySlug: Checks specific offer availability (e.g., caffe-nero).Implemented a Cobra/Viper-based Go CLI with the following commands:
bootstrap-login: Uses saved config when valid, otherwise performs env-based login and persists fresh session data.rewards: Lists all currently held vouchers and their expiry dates.check: Checks if the Caffè Nero offer is in stock or available to claim.claim: Attempts to claim the configured offer.watch: Polls availability and can auto-claim when stock appears.cp .env.example .env # fill in OCTOPUS_REFRESH_TOKEN and OCTOPUS_CLIENT_ID
export $(grep -v '^#' .env | xargs)
go run . login
go run . check --offer=caffe-nero
go run . watch --offer=caffe-nero --interval=10s --auto-claim
# Optional env-based configuration via Viper
export CLAIM_POLL_INTERVAL=1s
export CLAIM_POLL_TIMEOUT=45s
export CLAIM_MIN_ATTEMPTS=8
export HTTP_TIMEOUT=5m
export LOG_LEVEL=info
export LOG_FORMAT=text
go run . claim
--log-level, --log-format, --http-timeoutcheck: --offerclaim: --offer, --claim-poll-interval, --claim-timeout, --claim-min-attemptswatch: --offer, --interval, --auto-claim, --claim-poll-interval, --claim-timeout, --claim-min-attemptsThis repo includes:
Dockerfile using a FROM scratch runtime imagek8s/namespace.yaml for a dedicated bountybeacon namespacek8s/cronjob.yaml scheduled for Monday 03:00 (Europe/London)k8s/cronjob-wheel-of-fortune.yaml scheduled monthly to run spink8s/secret.example.yaml for the refresh token secretk8s/pvc.example.yaml for persistent /work storage (~/.bountybeacon.json)The cron job runs an init container for bootstrap-login, then the main container runs watch --auto-claim.
Only the init container references octopus-credentials env vars. The main container reads the persisted session file from /work/.bountybeacon.json.
The pod sets fsGroup: 65532 so the non-root containers can write to the mounted PVC at /work. If you previously bootstrapped with different ownership and still see permission denied for /work/.bountybeacon.json, remove the old file from the PVC once and rerun the job.
Build and push:
docker build -t gregarendse/bountybeacon:latest .
docker push gregarendse/bountybeacon:latest
Create namespace, secret, PVC, and apply CronJob:
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/secret.example.yaml
kubectl apply -f k8s/pvc.example.yaml
kubectl apply -f k8s/cronjob.yaml
kubectl apply -f k8s/cronjob-wheel-of-fortune.yaml
All Kubernetes manifests in k8s/ are scoped to the bountybeacon namespace.
If you want a different time, update spec.schedule in k8s/cronjob.yaml.
Contributions are welcome! Please read CONTRIBUTING.md before opening a PR.
Please report vulnerabilities privately — see SECURITY.md for details.
See CHANGELOG.md for a history of notable changes.
This project is licensed under the MIT Licence.
Content type
Image
Digest
sha256:cd513460f…
Size
2.9 MB
Last updated
about 1 month ago
docker pull gregarendse/bountybeacon