Initial commit

This commit is contained in:
Connor Johnstone
2026-03-17 14:14:46 -04:00
commit 305ddff278
27 changed files with 1897 additions and 0 deletions
@@ -0,0 +1,85 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Artists::Table)
.if_not_exists()
.col(
ColumnDef::new(Artists::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Artists::Name).text().not_null())
.col(ColumnDef::new(Artists::MusicbrainzId).text())
.col(
ColumnDef::new(Artists::AddedAt)
.date_time()
.not_null()
.default(Expr::current_timestamp()),
)
.col(
ColumnDef::new(Artists::TopSongs)
.text()
.not_null()
.default("[]"),
)
.col(
ColumnDef::new(Artists::SimilarArtists)
.text()
.not_null()
.default("[]"),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_artists_name")
.table(Artists::Table)
.col(Artists::Name)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_artists_musicbrainz_id")
.table(Artists::Table)
.col(Artists::MusicbrainzId)
.unique()
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Artists::Table).to_owned())
.await
}
}
#[derive(DeriveIden)]
pub(crate) enum Artists {
Table,
Id,
Name,
MusicbrainzId,
AddedAt,
TopSongs,
SimilarArtists,
}
@@ -0,0 +1,93 @@
use sea_orm_migration::prelude::*;
use super::m20260317_000001_create_artists::Artists;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Albums::Table)
.if_not_exists()
.col(
ColumnDef::new(Albums::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Albums::Name).text().not_null())
.col(ColumnDef::new(Albums::AlbumArtist).text().not_null())
.col(ColumnDef::new(Albums::Year).integer())
.col(ColumnDef::new(Albums::Genre).text())
.col(ColumnDef::new(Albums::CoverArtPath).text())
.col(ColumnDef::new(Albums::MusicbrainzId).text())
.col(ColumnDef::new(Albums::ArtistId).integer())
.foreign_key(
ForeignKey::create()
.name("fk_albums_artist_id")
.from(Albums::Table, Albums::ArtistId)
.to(Artists::Table, Artists::Id)
.on_delete(ForeignKeyAction::SetNull),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_albums_name")
.table(Albums::Table)
.col(Albums::Name)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_albums_artist_id")
.table(Albums::Table)
.col(Albums::ArtistId)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_albums_musicbrainz_id")
.table(Albums::Table)
.col(Albums::MusicbrainzId)
.unique()
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Albums::Table).to_owned())
.await
}
}
#[derive(DeriveIden)]
pub(crate) enum Albums {
Table,
Id,
Name,
AlbumArtist,
Year,
Genre,
CoverArtPath,
MusicbrainzId,
ArtistId,
}
@@ -0,0 +1,146 @@
use sea_orm_migration::prelude::*;
use super::m20260317_000001_create_artists::Artists;
use super::m20260317_000002_create_albums::Albums;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Tracks::Table)
.if_not_exists()
.col(
ColumnDef::new(Tracks::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Tracks::FilePath).text().not_null().unique_key())
.col(ColumnDef::new(Tracks::Title).text())
.col(ColumnDef::new(Tracks::Artist).text())
.col(ColumnDef::new(Tracks::Album).text())
.col(ColumnDef::new(Tracks::AlbumArtist).text())
.col(ColumnDef::new(Tracks::TrackNumber).integer())
.col(ColumnDef::new(Tracks::DiscNumber).integer())
.col(ColumnDef::new(Tracks::Duration).double())
.col(ColumnDef::new(Tracks::Genre).text())
.col(ColumnDef::new(Tracks::Year).integer())
.col(ColumnDef::new(Tracks::Codec).text())
.col(ColumnDef::new(Tracks::Bitrate).integer())
.col(ColumnDef::new(Tracks::FileSize).big_integer().not_null())
.col(ColumnDef::new(Tracks::Fingerprint).text())
.col(ColumnDef::new(Tracks::MusicbrainzId).text())
.col(ColumnDef::new(Tracks::ArtistId).integer())
.col(ColumnDef::new(Tracks::AlbumId).integer())
.col(ColumnDef::new(Tracks::FileMtime).date_time())
.col(
ColumnDef::new(Tracks::AddedAt)
.date_time()
.not_null()
.default(Expr::current_timestamp()),
)
.col(
ColumnDef::new(Tracks::UpdatedAt)
.date_time()
.not_null()
.default(Expr::current_timestamp()),
)
.foreign_key(
ForeignKey::create()
.name("fk_tracks_artist_id")
.from(Tracks::Table, Tracks::ArtistId)
.to(Artists::Table, Artists::Id)
.on_delete(ForeignKeyAction::SetNull),
)
.foreign_key(
ForeignKey::create()
.name("fk_tracks_album_id")
.from(Tracks::Table, Tracks::AlbumId)
.to(Albums::Table, Albums::Id)
.on_delete(ForeignKeyAction::SetNull),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_tracks_artist_id")
.table(Tracks::Table)
.col(Tracks::ArtistId)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_tracks_album_id")
.table(Tracks::Table)
.col(Tracks::AlbumId)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_tracks_title")
.table(Tracks::Table)
.col(Tracks::Title)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_tracks_artist")
.table(Tracks::Table)
.col(Tracks::Artist)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Tracks::Table).to_owned())
.await
}
}
#[derive(DeriveIden)]
pub(crate) enum Tracks {
Table,
Id,
FilePath,
Title,
Artist,
Album,
AlbumArtist,
TrackNumber,
DiscNumber,
Duration,
Genre,
Year,
Codec,
Bitrate,
FileSize,
Fingerprint,
MusicbrainzId,
ArtistId,
AlbumId,
FileMtime,
AddedAt,
UpdatedAt,
}
@@ -0,0 +1,103 @@
use sea_orm_migration::prelude::*;
use super::m20260317_000001_create_artists::Artists;
use super::m20260317_000002_create_albums::Albums;
use super::m20260317_000003_create_tracks::Tracks;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(WantedItems::Table)
.if_not_exists()
.col(
ColumnDef::new(WantedItems::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(WantedItems::ItemType).text().not_null())
.col(ColumnDef::new(WantedItems::ArtistId).integer())
.col(ColumnDef::new(WantedItems::AlbumId).integer())
.col(ColumnDef::new(WantedItems::TrackId).integer())
.col(
ColumnDef::new(WantedItems::Status)
.text()
.not_null()
.default("wanted"),
)
.col(
ColumnDef::new(WantedItems::AddedAt)
.date_time()
.not_null()
.default(Expr::current_timestamp()),
)
.col(
ColumnDef::new(WantedItems::UpdatedAt)
.date_time()
.not_null()
.default(Expr::current_timestamp()),
)
.foreign_key(
ForeignKey::create()
.name("fk_wanted_artist_id")
.from(WantedItems::Table, WantedItems::ArtistId)
.to(Artists::Table, Artists::Id)
.on_delete(ForeignKeyAction::Cascade),
)
.foreign_key(
ForeignKey::create()
.name("fk_wanted_album_id")
.from(WantedItems::Table, WantedItems::AlbumId)
.to(Albums::Table, Albums::Id)
.on_delete(ForeignKeyAction::Cascade),
)
.foreign_key(
ForeignKey::create()
.name("fk_wanted_track_id")
.from(WantedItems::Table, WantedItems::TrackId)
.to(Tracks::Table, Tracks::Id)
.on_delete(ForeignKeyAction::Cascade),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_wanted_items_status")
.table(WantedItems::Table)
.col(WantedItems::Status)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(WantedItems::Table).to_owned())
.await
}
}
#[derive(DeriveIden)]
pub(crate) enum WantedItems {
Table,
Id,
ItemType,
ArtistId,
AlbumId,
TrackId,
Status,
AddedAt,
UpdatedAt,
}
@@ -0,0 +1,101 @@
use sea_orm_migration::prelude::*;
use super::m20260317_000004_create_wanted_items::WantedItems;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(DownloadQueue::Table)
.if_not_exists()
.col(
ColumnDef::new(DownloadQueue::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(DownloadQueue::WantedItemId).integer())
.col(ColumnDef::new(DownloadQueue::Query).text().not_null())
.col(ColumnDef::new(DownloadQueue::SourceUrl).text())
.col(
ColumnDef::new(DownloadQueue::SourceBackend)
.text()
.not_null()
.default("ytdlp"),
)
.col(
ColumnDef::new(DownloadQueue::Status)
.text()
.not_null()
.default("pending"),
)
.col(ColumnDef::new(DownloadQueue::ErrorMessage).text())
.col(
ColumnDef::new(DownloadQueue::RetryCount)
.integer()
.not_null()
.default(0),
)
.col(
ColumnDef::new(DownloadQueue::CreatedAt)
.date_time()
.not_null()
.default(Expr::current_timestamp()),
)
.col(
ColumnDef::new(DownloadQueue::UpdatedAt)
.date_time()
.not_null()
.default(Expr::current_timestamp()),
)
.foreign_key(
ForeignKey::create()
.name("fk_download_wanted_item_id")
.from(DownloadQueue::Table, DownloadQueue::WantedItemId)
.to(WantedItems::Table, WantedItems::Id)
.on_delete(ForeignKeyAction::Cascade),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_download_queue_status")
.table(DownloadQueue::Table)
.col(DownloadQueue::Status)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(DownloadQueue::Table).to_owned())
.await
}
}
#[derive(DeriveIden)]
pub(crate) enum DownloadQueue {
Table,
Id,
WantedItemId,
Query,
SourceUrl,
SourceBackend,
Status,
ErrorMessage,
RetryCount,
CreatedAt,
UpdatedAt,
}
@@ -0,0 +1,73 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(SearchCache::Table)
.if_not_exists()
.col(
ColumnDef::new(SearchCache::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(SearchCache::QueryKey)
.text()
.not_null()
.unique_key(),
)
.col(ColumnDef::new(SearchCache::Provider).text().not_null())
.col(ColumnDef::new(SearchCache::ResultJson).text().not_null())
.col(
ColumnDef::new(SearchCache::CreatedAt)
.date_time()
.not_null()
.default(Expr::current_timestamp()),
)
.col(
ColumnDef::new(SearchCache::ExpiresAt)
.date_time()
.not_null(),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.name("idx_search_cache_expires")
.table(SearchCache::Table)
.col(SearchCache::ExpiresAt)
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(SearchCache::Table).to_owned())
.await
}
}
#[derive(DeriveIden)]
enum SearchCache {
Table,
Id,
QueryKey,
Provider,
ResultJson,
CreatedAt,
ExpiresAt,
}
+24
View File
@@ -0,0 +1,24 @@
use sea_orm_migration::prelude::*;
mod m20260317_000001_create_artists;
mod m20260317_000002_create_albums;
mod m20260317_000003_create_tracks;
mod m20260317_000004_create_wanted_items;
mod m20260317_000005_create_download_queue;
mod m20260317_000006_create_search_cache;
pub struct Migrator;
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![
Box::new(m20260317_000001_create_artists::Migration),
Box::new(m20260317_000002_create_albums::Migration),
Box::new(m20260317_000003_create_tracks::Migration),
Box::new(m20260317_000004_create_wanted_items::Migration),
Box::new(m20260317_000005_create_download_queue::Migration),
Box::new(m20260317_000006_create_search_cache::Migration),
]
}
}