Now, Next, Later
- Globbing scan for all *.mp3s.
- Now: Restrict the scan to a single directory like iTunes?
- Later: Other audio formats could be useful.
- Store the base path minus the file name?
- Read ID3v2 or possibly ID3v1 tags for metadata.
- Filter unique metadata for Artist and Album.
- Later: Merge records.
- Store metadata in database tables.
- Background worker
checksverifies Spotify or another music API for missing albums. - Create a UI to display artist information.
- Absolutely steal from prior art like Apple Music, Amazon Music, Spotify, etc. This should be familiar
- Send notifications.
- Now: In-app notifications as APIs are slowly polled throughout the month.
- Later: Email notifications?
- Next: Notification screen to view missing albums by artist.
- View artist by missing albums.
- Next: Different views like owned, not owned, or possibly wish list?
- Now: Mixed views that show what's owned vs missing? One single view is likely preferred with filtering added later.
- Later: Verify albums have all songs. Partial albums may count as incomplete.
- This likely changes the whole data format, we may store the full metadata including file name and full path.
- I may be entirely wrong about needing the path at any point. My mind says I need it but a scan of the entire iTunes 40gb is stupid fucking quick for what I expect. 5 seconds to read to the end of 40gb of files is impressive.
- Later: Merge capabilities
- This is likely where paths come in to resolve conflicts.
User logging into the system.
Technically the root-level object though we'll likely fudge it as an MVP. I would need the ID3 crawler to be user aware when it currently runs on localhost. The gen.auth scaffolding will take care of this.
Music artist, i.e. The Artist Formerly Known as Prince
.
Parent object created from ID3 crawler of at least a name
to search Spotify. We are looking for new albums by artist.
Music artist's album(s) i.e. Periphery III: Select Difficulty
.
Albums are either owned as found by the ID3 crawler or not as found on Spotify. Consists of the album name
, year
, genre
and is_owned
.
This is where stuff starts to fall down because there are settings for scanning (local) and verifying the API which can live anywhere. The v3 scanner would need to be configured independently and execute independently in this scenario. If I make this a standalone application that solves most of this. I can still put up a demo on Fly.io, scanning would just not be functional as the local directories wouldn't exist there.
Collection of notifications
Potential notification types
- Album not owned and verified initially.
- New releases. These are within x date, 6 months to a year? What defines a new release?
- Over the course of using the application, these should pop up ahead of time like on iTunes.
- This whole application was designed around replicating how iTunes alerts on new albums for a single artist. We want a UI that can handle and showcase several.
- Email, Slack, Discord, and possibly other destinations? - Next or Later.
Notification requiring action
Potential action types
- On startup: ID3 tag ran x days ago, do you wish to run it now?
- ID3 crawler has x albums but Spotify reports zero found. Did Spotify choose the right artist at index 0? I'm seeing artists like Persephone or Underoath when searching for Periphery. There looks to be a fuzzy search happening which we likely don't want.
- Other corrective notifications like album names being close by
String.jaro_distance
. - ID3 is notoriously problematic as people ripping their own collection can easily supply the wrong metadata.
- User -
mix.gen.auth
- Artist
name:string
path:string
- Calculated by ID3 tag parent parent directory, if the names match within a threshold.
image_url:string
- Spotify
verified_at:utc_datetime_usec
mix phx.gen.live Artists Artist artists name:string path:string image_url:string verified_at:utc_datetime_usec
- Album
name:string
genre:string
- Periphery is
Progressive Metal / Math Metal / Djent
in ID3. Spotify lists this on the artist as"djent", "melodic metalcore", "progressive metal", "progressive metalcore"
.
- Periphery is
year:string
- ID3 as string.
- Spotify as
release_date
andrelease_date_precision
which may be day/datetime oriented.
is_owned:boolean
- I like knowing field types by naming convention. The
is_
boolean convention is something I picked up long ago.
- I like knowing field types by naming convention. The
path:string
- Path to the ID3 tag's base directory.
image_url:string
- Extracted from ID3 or Spotify.
mix phx.gen.live Albums Album albums name:string genre:string year:string release_date:date is_owned:boolean path:string image_url:string artist_id:references:artists
- Settings
scanned_at:utc_datetime_usec
verified_at:utc_datetime_usec
- Next
directories
: embedded JSON?
- Notifications
album_id:integer
icon:string
subject:string
body:text
url:text
type:enum
- See https://hexdocs.pm/ecto/Ecto.Enum.htmlseen_at:utc_datetime_usec
mix phx.gen.live Notifications Notification notifications icon:string subject:string body:text url:text type:string seen_at:utc_datetime_usec album_id:references:albums
- Actions - Next
table_name:string
table_id:integer
title:string
payload:text
type:enum
- See https://hexdocs.pm/ecto/Ecto.Enum.htmlcompleted_at:utc_datetime_usec
I see in my mind an application that takes the same sidebar as Livebeats as the left panel that looks something like [https://tailwindcomponents.com/component/navigation-component].
- Dashboard? - Next/Later
- Search? - Next
- Music
- Artists with badge count(s)
- Albums with badge count(s)
- Account
- Profile
- Settings
- Notifications with badge
- Actions?
- Sticky footer
- Message panel
- Click to open log
- Icon panel
- Icon coloring showing application state. Should link to actions?
- Vertical scrolling list
- Filter?
- Sort by Name or Date?
- Image, uses default if no
image_url
found - Name
- Albums side panel
- Name
- X Albums
- Dot Menu
- Verify for new albums
- Image, uses default if no
image_url
found - Name
- 1st Genre * Year
- Missing albums opacity
- Grid of images, uses default if no
image_url
found- Name | Year
- Artist Name
- Missing albums opacity
- Filter by found, not found
- Wishlist - Next
- Directories
- Table of directory names
- CRUD buttons
- Schedules
- Scan
- API Verification
- Scan
- Scan on startup
- Verify
- Verify automatically on new artist
- Retry x times
- Exponential backoff - Next
The UI will need to be able to perform any steps manually, namely the scan and verify.
Scanning should be a named supervised GenServer.
- start message
- Run on startup?
- Set
is_scanning
conditional to lock and prevent multiple full scans. - Run full scan algorithm.
- scan path message
- Handled any portion of the path, could be a recursive function to walk the directory tree if necessary.
- Handles each path configured in the settings.
- scan - Scan module
- Build an enumerable of ID3 tags.
- For each tag, create album then create each artist.
- When artist is complete, send verify artist name event.
Verify should also be a named GenServer.
- start message
- Run on startup?
- Set
is_verifying
conditional to lock and prevent multiple full system verifications. - Run full verify algorithm.
- verify artist name message
- For each album returned, String.jaro_distance to try to match each name in the database.
- Add missing album with
is_owned = false
. - Send notification, if within a year it should be a new release otherwise a found.
- verify - Verify module
- Does Spotify library handle retries? Exponential backoff? Caching? Req does so much and it could potentially be trivial to handle OAuth.