# Scrobble

This section documents the **scrobble pipeline** under `providers/scrobble/`.

It also covers the legacy webhook bridge under `providers/webhooks/`.

{% tabs %}
{% tab title="End users" %}
{% hint style="info" %}
If you want setup steps, use the UI docs: [Scrobble](/crosswatch/scrobble.md) and [Watcher](/crosswatch/scrobble/watcher.md).
{% endhint %}

### What scrobbling does

Scrobbling pushes **playback progress** to trackers in real time.

It uses three pieces:

* providers (Plex/Jellyfin/Emby) that produce events
* a dispatcher that filters and dedupes
* sinks (Trakt/SIMKL/MDBList) that send events outbound

### Pages in this section

* Event producers: [Providers](/blueprint-architecture/scrobble/providers.md)
* Outbound senders: [Sink](/blueprint-architecture/scrobble/sink.md)
* State files: [Services](/blueprint-architecture/scrobble/services.md)
* Deprecated: [Webhooks](/blueprint-architecture/scrobble/webhooks.md)

### Typical flow

```mermaid
flowchart TD
  P[Playback event] --> PARSE[Parse -> ScrobbleEvent]
  PARSE --> F[Filter + dedupe]
  F --> S[Send to sinks]
  F --> CW[Update currently_watching]
  F -->|if completed| WL[Auto-remove from watchlist]
```

{% endtab %}

{% tab title="Power users" %}

### Code map

* core model + dispatcher: `providers/scrobble/scrobble.py`
* watch providers: `providers/scrobble/<provider>/watch.py`
* sinks: `providers/scrobble/<sink>/sink.py`
* runtime state writers: `providers/scrobble/currently_watching.py`, `providers/scrobble/_auto_remove_watchlist.py`
* legacy webhook bridge: `providers/webhooks/*.py`

### Data model: `ScrobbleEvent`

Common fields:

* `action`: `start`, `pause`, `stop`
* `media_type`: `movie`, `episode`
* `ids`: IMDb/TMDb/TVDb tokens (when present)
* `progress`: 0–100
* `server_uuid`, `username`, `session_key` for filtering and dedupe
* `raw` payload for debugging

### Parsing sources

Supported Plex shapes:

* PlaySessionStateNotification (`from_plex_pssn`)
* flat playing objects (`from_plex_flat_playing`)
* webhook wrapper (`from_plex_webhook`)

ID extraction relies on Plex GUID patterns:

* `imdb://tt...`
* `tmdb://...`
* `thetvdb://...`

### Dispatcher guardrails

The dispatcher enforces:

* server UUID + username allowlists
* pause debounce (defaults to 5s)
* per-session last action and last progress tracking

### State output

* `/config/.cw_state/currently_watching.json`
* `/config/.cw_state/watchlist_wl_autoremove.json` (TTL dedupe)
  {% endtab %}
  {% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.crosswatch.app/blueprint-architecture/scrobble.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
