Skip to content

bin101/kudosy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

122 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Kudosy

Kudosy logo

Kudosy automatically gives kudos on Strava to activities in your following feed β€” based on configurable distance and duration rules, with human-like random timing so it doesn't look like a bot.

⚠️ Strava Terms of Service notice: Kudosy authenticates using your personal _strava4_session browser cookie (web session), not the official Strava API/OAuth. This is a personal/educational tool β€” use it responsibly. Keep the scheduler interval generous and rely on the built-in delays and jitter to stay under the radar. You are solely responsible for compliance with Strava's ToS.

Features

  • πŸ€– β†’ πŸ§‘ Human-like timing β€” randomised interval jitter, per-kudos delays, shuffled send order, and automatic backoff on Strava rate limits (HTTP 429) or repeated send failures
  • βš™οΈ Web UI β€” four tabs (Feed, Configuration, Statistics, Status & Log) in five languages (DE/EN/FR/ES/IT), with light/dark theme (system default + manual override)
  • 🧩 Flexible rules β€” catch-all, per-category and per-sport-type distance/duration thresholds, activity-name regex overrides, per-athlete allow/deny lists
  • πŸ” Scheduler β€” configurable interval + jitter, quiet-hours matrix (7Γ—24, drag-to-paint, timezone-aware), enable/disable, dry-run mode
  • πŸ“‘ Live feed view β€” see your following feed with per-activity kudo decisions and reasons, send single kudos manually, filter by status/sport/text
  • πŸ“Š Statistics β€” run history with charts and per-sport aggregations
  • πŸ”” Notifications β€” webhook alerts (ntfy, Slack, Discord, Gotify or generic HTTP) on runs, auth errors, and as a daily digest
  • πŸͺ΅ Live log β€” the log tab streams run output in real time via Server-Sent Events
  • ⬆️ Update check β€” footer hint when a newer release is available (optional, max. 1 check/12 h)
  • πŸ’Ύ Backup β€” export/import config + settings as JSON (session cookie excluded from exports)
  • 🐳 Docker-first β€” single docker compose up to run, multi-arch images on GHCR
  • πŸ§ͺ Test-driven β€” β‰₯85% test coverage, pure functions tested in isolation

Quick Start

With Docker (recommended)

# Clone the repo
git clone https://github.com/bin101/kudosy.git
cd kudosy

# Copy the example config and fill in your cookie + athlete ID
cp data/config.example.yaml data/config.yaml
$EDITOR data/config.yaml

# Start
docker compose up -d
# Open http://localhost:8080

Without Docker (local Python)

python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
KUDOSY_DATA_DIR=./data KUDOSY_PORT=8080 python -m kudosy

Getting Your Strava Session Cookie

  1. Log in to strava.com in your browser.
  2. Open DevTools β†’ Application β†’ Cookies β†’ https://www.strava.com.
  3. Copy the value of _strava4_session.
  4. Paste it into data/config.yaml as stravaSessionCookie, or enter it in the web UI.

The cookie expires β€” if Kudosy suddenly stops finding activities, refresh it here.

Configuration

All config lives in ./data/ (mounted as /data in Docker):

File Purpose
config.yaml Your session cookie, athlete ID, allow/deny lists, catch-all + per-sport rules
settings.json Scheduler interval, jitter, delays, quiet-hours matrix, notifications, dry-run flag
athlete-labels.json Cached athlete ID β†’ name lookups
athlete-avatars.json Cached athlete ID β†’ avatar URL lookups
kudoed-activities.json Already-kudoed activity IDs (skip cache across runs)
activity-cache.json Last parsed feed snapshot (survives restarts)
run-history.json Compact per-run history entries (feeds the Statistics tab)
last-digest.json Timestamp of the last daily-digest notification
last-run.log Output of the most recent run

A legacy defaults.yaml (from older versions) is automatically migrated into config.yaml on first boot and renamed to defaults.yaml.migrated.

See data/config.example.yaml for a fully annotated example.

Human-Like Timing

Kudosy has several layers of randomness and restraint to avoid a detectable machine pattern:

  1. Interval jitter: each scheduled run fires after intervalMinutes Β± jitterMinutes (uniform random). Default: 60 Β± 15 minutes.
  2. Per-kudos delay: between each individual kudo POST, Kudosy waits a random duration in [minKudosDelaySeconds, maxKudosDelaySeconds]. Default: 3–25 seconds.
  3. Shuffle order: the list of activities to kudo can be shuffled randomly before sending.
  4. Quiet hours: the 7Γ—24 schedule matrix restricts kudos to allowed weekday/hour slots in your timezone.
  5. Rate-limit backoff: on HTTP 429 (or three consecutive failed sends) the remaining kudos of the run are skipped; the next scheduled run retries naturally.

All timing parameters are configurable in the web UI on the Configuration tab.

Docker Image

Pre-built multi-arch images (amd64 + arm64) are published to GitHub Container Registry:

docker pull ghcr.io/bin101/kudosy:latest

Tags: latest (from main), vX.Y.Z (releases), X.Y (minor), commit SHA.

Development

# Install
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

# TDD cycle: write tests first, then implementation
pytest tests/unit/          # pure functions (fast)
pytest --cov=kudosy --cov-report=term-missing

# Lint & type-check
ruff check src tests
ruff format --check src tests
mypy src

See CLAUDE.md for the full architecture guide.

Versioning

Semantic Versioning via pyproject.toml. Releases are driven by Conventional Commits and automated with release-please. See CHANGELOG.md for release history.

License

MIT β€” see LICENSE.

About

Automatically give Kudos to your Strava friends. Never miss a workout, always show support. πŸƒβ€β™‚οΈπŸš΄β€β™€οΈ

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors