Commit Graph

1433 Commits

Author SHA1 Message Date
Claudio Ortolina 57223821d4 Remove obsolete TODO 2025-07-04 15:50:39 +01:00
Claudio Ortolina 1688fa3663 Improve main action button group in scrobble rules page 2025-07-04 15:45:21 +01:00
Claudio Ortolina 29ea381167 Render scrobble rule status with badge 2025-07-04 14:55:46 +01:00
Claudio Ortolina 40346d9123 Render scrobble rule type with badge 2025-07-04 14:53:27 +01:00
Claudio Ortolina b689b99be4 Fix stream container for scrobble rules 2025-07-04 14:52:28 +01:00
Claudio Ortolina aee08cc2bb Use Enum for scrobble rule type 2025-07-04 14:23:19 +01:00
Claudio Ortolina 81f0ec8830 Render scrobble rules list with Fluxon table 2025-07-04 14:07:35 +01:00
Claudio Ortolina 6518a4b10e Use Fluxon from HTML helpers 2025-07-04 13:41:15 +01:00
Claudio Ortolina f395fe0f4a Fix placeholder text for rule type select input 2025-07-04 13:41:00 +01:00
Claudio Ortolina 904a65c376 Make editing modal larger 2025-07-04 13:36:45 +01:00
Claudio Ortolina bb6c838d6a Remove unnecessary explanation text 2025-07-04 13:36:29 +01:00
Claudio Ortolina d6b77586c1 Consistently road scrobble rules when creating or editing a scrobble rule 2025-07-04 13:34:40 +01:00
Claudio Ortolina 714dc0b8cc Use textarea for description 2025-07-04 13:31:16 +01:00
Claudio Ortolina 93e10bc5d9 Remove excessively defensive coding 2025-07-03 21:18:21 +01:00
Claudio Ortolina b2bc5f07f7 Remove unnecessary code 2025-07-03 21:10:59 +01:00
Claudio Ortolina 024ba38b63 Use Ecto.UUID instead of hand-rolled type 2025-07-03 21:07:42 +01:00
Claudio Ortolina d91685b646 First rough implementation of scrobble rules (Claude)
This plan outlines the implementation of functionality to manage
arbitrary rules for fixing data in the `scrobbled_tracks` table. The
system will support two types of transformations:

1. **Album Rule**: Update the album MusicBrainz ID of all tracks
belonging to a specific album (identified by album title)
2. **Artist Rule**: Update the artist MusicBrainz ID of all tracks
belonging to a specific artist (identified by artist name)

- `scrobbled_tracks` table exists with the following structure:
  - `scrobbled_at_uts` (integer, primary key)
  - `musicbrainz_id` (string) - track MusicBrainz ID
  - `title` (string) - track title
  - `cover_url` (string)
  - `scrobbled_at_label` (string)
  - `artist` (map) - embedded artist data with `musicbrainz_id` and
`name`
  - `album` (map) - embedded album data with `musicbrainz_id` and
`title`
  - `last_fm_data` (map) - raw Last.fm API response

- `LastFm.Track` - Schema for scrobbled tracks
- `LastFm.Artist` - Embedded artist schema
- `LastFm.Album` - Embedded album schema

- Main navigation has Stats, Collection, Wishlist sections
- "More" dropdown contains development tools and utilities
- Uses Phoenix LiveView for interactive components

**File**:
`priv/repo/migrations/YYYYMMDDHHMMSS_create_scrobble_rules.exs`

Create `scrobble_rules` table with:

- `id` (primary key)
- `type` (string) - "album" or "artist"
- `match_value` (string) - album title or artist name to match
- `target_musicbrainz_id` (string) - MusicBrainz ID to set
- `enabled` (boolean) - whether rule is active
- `description` (text) - optional description for the rule
- `inserted_at` (timestamp)
- `updated_at` (timestamp)

Indexes:

- `type, match_value` (compound index for efficient matching)
- `enabled` (for filtering active rules)

**File**: `lib/music_library/scrobble_rules/scrobble_rule.ex`

Create Ecto schema with:

- Field definitions matching migration
- Validations:
  - `type` must be "album" or "artist"
  - `match_value` required and non-empty
  - `target_musicbrainz_id` required and non-empty
  - `enabled` defaults to true
- Changeset functions for create/update operations

**File**: `lib/music_library/scrobble_rules.ex`

Implement context functions:

- `list_scrobble_rules(opts \\ [])` - list all rules with optional
filtering
- `get_scrobble_rule!(id)` - get specific rule by ID
- `create_scrobble_rule(attrs)` - create new rule
- `update_scrobble_rule(rule, attrs)` - update existing rule
- `delete_scrobble_rule(rule)` - delete rule
- `change_scrobble_rule(rule, attrs \\ %{})` - create changeset
- `list_enabled_rules()` - get only enabled rules for worker
- `apply_album_rule(rule)` - apply album transformation
- `apply_artist_rule(rule)` - apply artist transformation
- `apply_all_rules()` - apply all enabled rules

**File**: `lib/music_library_web/components/layouts/app.html.heex`

Add new navigation link in the "More" dropdown:

- Icon: `hero-adjustments-horizontal`
- Label: "Scrobble Rules"
- Route: `/scrobble-rules`
- Position: After "Oban" link, before separator

**File**: `lib/music_library_web/router.ex`

Add new LiveView routes in the authenticated scope:

- `/scrobble-rules` - index page
- `/scrobble-rules/new` - create new rule
- `/scrobble-rules/:id/edit` - edit existing rule

**File**: `lib/music_library_web/live/scrobble_rules_live/index.ex`

Implement LiveView with:

- List view showing all rules with status indicators
- Create/Edit forms with validation
- Delete confirmation
- Filter controls (by type, enabled/disabled)
- Manual rule application triggers
- Real-time updates via PubSub

**Template**:
`lib/music_library_web/live/scrobble_rules_live/index.html.heex`

- Table layout with rule details
- Action buttons (Edit, Delete, Apply)
- Form components for create/edit
- Status indicators for enabled/disabled rules

**File**:
`lib/music_library_web/live/scrobble_rules_live/form_component.ex`

Create reusable form component:

- Type selection (album/artist)
- Match value input with validation
- Target MusicBrainz ID input
- Description textarea
- Enable/disable toggle
- Save/Cancel actions

Where possible, use the components available at
<https://docs.fluxonui.com/1.1.4/overview.html>.

**File**: `lib/music_library/scrobble_rules/worker.ex`

Implement Oban worker:

- Scheduled to run periodically (e.g., every 30 minutes)
- Fetches all enabled rules
- Applies each rule in sequence
- Logs application results
- Handles errors gracefully
- Tracks last application time

**File**: `test/music_library/scrobble_rules_test.exs`

- Test all context functions
- Test rule application logic
- Test edge cases and error handling

**File**: `test/music_library/scrobble_rules/scrobble_rule_test.exs`

- Test schema validations
- Test changeset functions
- Test constraint validations

**File**: `test/music_library_web/live/scrobble_rules_live_test.exs`

- Test LiveView interactions
- Test form submissions
- Test real-time updates
- Test navigation and routing

**File**: `test/music_library/scrobble_rules/worker_test.exs`

- Test job execution
- Test rule application
- Test error handling
- Test scheduling

- Ensure atomic operations when applying rules
- Validate MusicBrainz IDs before applying
- Log all transformations for audit trail

- Index optimization for rule matching
- Batch processing for large datasets
- Rate limiting for external API calls

- Clear feedback on rule application
- Preview mode to show what would change
- Bulk operations for managing multiple rules
- Export/import functionality for rule sets

- Input validation and sanitization
- Rate limiting on rule creation
- Audit logging for all changes

```sql
-- scrobble_rules table
CREATE TABLE scrobble_rules (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  type TEXT NOT NULL CHECK (type IN ('album', 'artist')),
  match_value TEXT NOT NULL,
  target_musicbrainz_id TEXT NOT NULL,
  enabled BOOLEAN NOT NULL DEFAULT TRUE,
  description TEXT,
  inserted_at TIMESTAMP NOT NULL,
  updated_at TIMESTAMP NOT NULL
);

CREATE INDEX idx_scrobble_rules_type_match ON scrobble_rules(type,
match_value);
CREATE INDEX idx_scrobble_rules_enabled ON scrobble_rules(enabled);
```

```
lib/music_library/
├── scrobble_rules/
│   ├── scrobble_rule.ex          # Schema
│   └── worker.ex                 # Oban worker
└── scrobble_rules.ex             # Context

lib/music_library_web/
└── live/
    └── scrobble_rules_live/
        ├── index.ex              # LiveView
        ├── index.html.heex       # Template
        └── form_component.ex     # Form component

priv/repo/migrations/
└── YYYYMMDDHHMMSS_create_scrobble_rules.exs

test/
├── music_library/
│   ├── scrobble_rules_test.exs
│   └── scrobble_rules/
│       ├── scrobble_rule_test.exs
│       └── worker_test.exs
└── music_library_web/
    └── live/
        └── scrobble_rules_live_test.exs
```

1. Database migration and schema
2. Context module with basic CRUD operations
3. LiveView interface for rule management
4. Navigation and routing updates
5. Periodic worker implementation
6. Comprehensive testing
7. Documentation and deployment

This plan ensures a robust, maintainable solution that integrates
seamlessly with the existing Music Library application architecture.
2025-07-03 16:47:08 +01:00
Claudio Ortolina f70cb317ac Update dependencies
req 0.5.12 => 0.5.14
2025-07-02 14:39:42 +01:00
Claudio Ortolina 6f72819b90 Update dependencies
quokka 2.7.1 => 2.8.0
2025-07-02 09:15:58 +01:00
Claudio Ortolina 2fb91a961b Update dependencies
plug 1.18.0 => 1.18.1
2025-07-01 19:19:08 +01:00
Claudio Ortolina f54d7744cf Pass Fluxon secrets when building docker locally 2025-06-29 19:20:29 +01:00
Claudio Ortolina c359444758 No need to fetch tracks when changing scrobble activity mode 2025-06-29 09:04:52 +01:00
Claudio Ortolina 82e9d3c5a7 Extract markup from stats live to separate set of components 2025-06-29 08:49:12 +01:00
Claudio Ortolina 088fd1624a Pick better perf metrics 2025-06-29 08:37:41 +01:00
Claudio Ortolina e5501638a4 Update claude permissions 2025-06-29 08:37:41 +01:00
Claudio Ortolina f8628cc2aa Update tailwind from 4.1.10 to 4.1.11 2025-06-29 08:37:39 +01:00
Claudio Ortolina f0d8e84221 Update npm dependencies 2025-06-25 20:45:13 +03:00
Claudio Ortolina c591d39f52 Update dependencies
live_debugger 0.2.0 => 0.3.0
2025-06-25 20:25:25 +03:00
Claudio Ortolina 08bc50d5dd Use tabs for scrobble activity toggle 2025-06-25 12:05:23 +03:00
Claudio Ortolina 0c84adde59 Use tabs for top artists and top albums 2025-06-25 11:43:58 +03:00
Claudio Ortolina 9a35012d15 Update dependencies
exqlite 0.32.0 => 0.32.1
tidewave 0.1.9 => 0.1.10
2025-06-25 08:23:50 +03:00
Claudio Ortolina 03e4c6195b Update dependencies
db_connection 2.7.0 => 2.8.0
ecto 3.13.1 => 3.13.2
ecto_sql 3.13.1 => 3.13.2
ecto_sqlite3 0.20.0 => 0.21.0 (minor)
phoenix_ecto 4.6.4 => 4.6.5
req 0.5.11 => 0.5.12

Restores old form of last_fm_test which had changed to accomodate a
change of default of Req.
2025-06-24 20:19:12 +03:00
Claudio Ortolina d5dc07d66c Add Meer to polyfillable artists 2025-06-24 09:16:58 +03:00
Claudio Ortolina ba6224e7e4 Update dependencies
tidewave 0.1.8 => 0.1.9
2025-06-24 08:13:52 +03:00
Claudio Ortolina c53d09dd24 Update dependencies
req 0.5.10 => 0.5.11

Requires a change in test logic due to automatic reading of body.
2025-06-23 16:59:14 +03:00
Claudio Ortolina cc5f5c7d8b Update dependencies
Move to circular_buffer 1.0, as it's identical to 0.4.2
2025-06-23 09:31:56 +03:00
Claudio Ortolina 0ad67f10c6 Use prefix for npm tasks instead of dir 2025-06-21 16:44:47 +03:00
Claudio Ortolina e2c2c6d547 Add tooltips for scrobble activity debug info 2025-06-21 15:20:24 +03:00
Claudio Ortolina a9d27059c4 Update dependencies
circular_buffer 0.4.1 => 0.4.2
ecto 3.12.6 => 3.13.1
ecto_sql 3.12.1 => 3.13.1
ecto_sqlite3 0.19.0 => 0.20.0 (minor)
exqlite 0.31.0 => 0.32.0 (minor)

Includes handling of deprecation for literal/1 to identifier/1
2025-06-21 09:10:57 +03:00
Claudio Ortolina 0739e12ad3 Polyfill scrobbled tracks every hour 2025-06-20 22:43:04 +03:00
Claudio Ortolina b091fa4d86 Fix line height for record detail titles 2025-06-20 22:30:18 +03:00
Claudio Ortolina 719f6cc8bb Increase memory size to 2048mb 2025-06-19 17:51:23 +03:00
Claudio Ortolina 35e060613b Add function to backfill missing data in scrobbled tracks 2025-06-19 17:38:51 +03:00
Claudio Ortolina 25634f5ee7 Exclude counts without album title from top albums 2025-06-19 17:21:16 +03:00
Claudio Ortolina f3425d8cb9 Add top artist and top albums of all time
Executed by Claude
2025-06-19 17:17:51 +03:00
Claudio Ortolina ccaf44be64 Update dependencies
quokka 2.7.0 => 2.7.1
2025-06-16 22:31:49 +03:00
Claudio Ortolina 9b20db762d Show top artists in stats page 2025-06-16 16:47:35 +03:00
Claudio Ortolina 53e7818130 Set DBUI_URL for dev 2025-06-16 12:03:18 +03:00
Claudio Ortolina 24b34d57d2 Update dependencies
floki 0.37.1 => 0.38.0 (minor)
quokka 2.6.0 => 2.7.0

Includes application of expensive enum check quokka rule
2025-06-16 11:47:07 +03:00
Claudio Ortolina 753615c57f Improve top albums
Makes it timezone aware, so that it can round up to the beginning of day
2025-06-15 12:12:04 +03:00