Colin Powell 29fc493cc2 Rewrite fasting trend algorithm and add comprehensive tests
- Replace day-iteration algorithm with pair-based approach for fasting
  detection. Iterate consecutive food scrobble pairs and mark foodless
  days between them as fasting days.

- Handle consecutive-day periodic fasting: when two food scrobbles are on
  consecutive days with a gap >= periodic_threshold but < full_threshold,
  mark the later day as a periodic fast (user's original bug fix).

- Fix _dt test helper to use replace() instead of subtracting hours,
  producing correct timestamps (e.g., '3 days ago at 18:46' instead of
  '3 days + 18h46m ago').

- Fix total_days off-by-one: removed +1 from inclusive day count so a
  'last_30' period correctly reports 30 days.

- Add _drinks_on_day() for per-day drink detection (replaces whole-
  window _drinks_in_window for more accurate liquid fasting detection).

- Fix Beer test fixture to use styles M2M field instead of non-existent
  beer_style attribute.

- Add 26 test cases covering: classification, short gaps, periodic/
  full/liquid fasting, multi-day gaps, vacation exemptions, custom
  thresholds, streaks, mixed types, edge cases.

Reasoning:
The original day-iteration algorithm had fundamental issues: it marked
days with food as fasting (since it only checked prev/next food times),
it didn't filter out normal (< periodic) gaps, and the _dt helper was
misinterpreting hour parameters. The new pair-based approach is cleaner:
for each consecutive food scrobble pair, we mark the foodless days
between them. This naturally handles multi-day fasts and correctly
avoids marking food-eating days as fasting. The consecutive-day periodic
rule preserves the user's original intent of detecting overnight fasts
between meals.
2026-07-19 13:11:29 -04:00
2026-06-30 16:26:07 -04:00
2026-06-15 12:38:21 -04:00
2026-06-05 14:58:35 -04:00
2023-01-20 13:02:32 -05:00
2026-03-02 22:43:53 -05:00
2026-06-05 14:58:35 -04:00
2023-03-04 17:29:25 -05:00
2026-07-17 15:35:57 -04:00
2026-05-24 12:47:12 -04:00
2023-06-01 19:47:32 -04:00

Vrobbler

Build Status

Vrobbler is a pretty simple Django-powered web app for scrobbling video plays from you favorite Jellyfin installation.

At the most basic level, you should be able to run pip install vrobbler to the latest version from pypi.org.

Then configure a handful of options in your vrobbler.conf files, which can live in /etc/ or /usr/local/etc/ depending on your configuration.

You can checkout the scrobbler.conf.example file in the source for this project, or refer to the following guide:

VROBBLER_DEBUG=True
VROBBLER_JSON_LOGGING=True
VROBBLER_LOG_LEVEL="DEBUG"
VROBBLER_MEDIA_ROOT = "/media/"
VROBBLER_TMDB_API_KEY = "<key>"
VROBBLER_KEEP_DETAILED_SCROBBLE_LOGS=True
VROBBLER_DATABASE_URL="postgres://vrobbler:<pass>@db.service:5432/vrobbler"
VROBBLER_REDIS_URL="redis://:<pass>@cache.service:6379/0"

Database Backup

A backup command is available via ./manage.py backup_database (also runs on a cron schedule via Celery). It dumps the database with pg_dump, compresses with gzip, and optionally copies the backup to a remote host via SCP.

Configure these additional settings as needed:

VROBBLER_DB_BACKUP_SSH_KEY="/path/to/ssh/private/key"
VROBBLER_DB_BACKUP_SSH_DEST="user@backup.example.com:/remote/path/"
VROBBLER_DB_BACKUP_NTFY_URL="https://ntfy.sh/your-topic"
  • VROBBLER_DB_BACKUP_SSH_KEY — Path to the SSH private key used for remote copy.
  • VROBBLER_DB_BACKUP_SSH_DEST — SCP destination (user@host:path). If set, the backup is copied to the remote host and old backups are pruned.
  • VROBBLER_DB_BACKUP_LOCAL_DIR — Local directory for backup storage. Defaults to /var/backups/. Backups are stored in a vrobbler/ subdirectory.
  • VROBBLER_DB_BACKUP_NTFY_URL — ntfy.sh URL for success notifications. Defaults to https://ntfy.unbl.ink/backups.

Retention is hardcoded: keeps daily backups for 7 days, plus one per month for 12 months.

Description
No description provided
Readme 22 MiB
Languages
Python 86.7%
HTML 13.2%