mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-01 19:47:37 +03:00
Use structs
lib to map models to DB. Fix #1266
This commit is contained in:
parent
344d7a4392
commit
c831dc4cdf
22 changed files with 207 additions and 235 deletions
1
go.mod
1
go.mod
|
@ -16,6 +16,7 @@ require (
|
|||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/djherbis/fscache v0.10.2-0.20201024185917-a0daa9e52747
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/go-chi/chi/v5 v5.0.3
|
||||
github.com/go-chi/cors v1.2.0
|
||||
github.com/go-chi/httprate v0.5.1
|
||||
|
|
2
go.sum
2
go.sum
|
@ -204,6 +204,8 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
|
|||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
|
|
|
@ -3,39 +3,39 @@ package model
|
|||
import "time"
|
||||
|
||||
type Album struct {
|
||||
Annotations
|
||||
Annotations `structs:"-"`
|
||||
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
Name string `json:"name"`
|
||||
CoverArtPath string `json:"coverArtPath"`
|
||||
CoverArtId string `json:"coverArtId"`
|
||||
ArtistID string `json:"artistId" orm:"column(artist_id)"`
|
||||
Artist string `json:"artist"`
|
||||
AlbumArtistID string `json:"albumArtistId" orm:"column(album_artist_id)"`
|
||||
AlbumArtist string `json:"albumArtist"`
|
||||
AllArtistIDs string `json:"allArtistIds" orm:"column(all_artist_ids)"`
|
||||
MaxYear int `json:"maxYear"`
|
||||
MinYear int `json:"minYear"`
|
||||
Compilation bool `json:"compilation"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
SongCount int `json:"songCount"`
|
||||
Duration float32 `json:"duration"`
|
||||
Size int64 `json:"size"`
|
||||
Genre string `json:"genre"`
|
||||
Genres Genres `json:"genres"`
|
||||
FullText string `json:"fullText"`
|
||||
SortAlbumName string `json:"sortAlbumName,omitempty"`
|
||||
SortArtistName string `json:"sortArtistName,omitempty"`
|
||||
SortAlbumArtistName string `json:"sortAlbumArtistName,omitempty"`
|
||||
OrderAlbumName string `json:"orderAlbumName"`
|
||||
OrderAlbumArtistName string `json:"orderAlbumArtistName"`
|
||||
CatalogNum string `json:"catalogNum,omitempty"`
|
||||
MbzAlbumID string `json:"mbzAlbumId,omitempty" orm:"column(mbz_album_id)"`
|
||||
MbzAlbumArtistID string `json:"mbzAlbumArtistId,omitempty" orm:"column(mbz_album_artist_id)"`
|
||||
MbzAlbumType string `json:"mbzAlbumType,omitempty"`
|
||||
MbzAlbumComment string `json:"mbzAlbumComment,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
Name string `structs:"name" json:"name"`
|
||||
CoverArtPath string `structs:"cover_art_path" json:"coverArtPath"`
|
||||
CoverArtId string `structs:"cover_art_id" json:"coverArtId"`
|
||||
ArtistID string `structs:"artist_id" json:"artistId" orm:"column(artist_id)"`
|
||||
Artist string `structs:"artist" json:"artist"`
|
||||
AlbumArtistID string `structs:"album_artist_id" json:"albumArtistId" orm:"column(album_artist_id)"`
|
||||
AlbumArtist string `structs:"album_artist" json:"albumArtist"`
|
||||
AllArtistIDs string `structs:"all_artist_ids" json:"allArtistIds" orm:"column(all_artist_ids)"`
|
||||
MaxYear int `structs:"max_year" json:"maxYear"`
|
||||
MinYear int `structs:"min_year" json:"minYear"`
|
||||
Compilation bool `structs:"compilation" json:"compilation"`
|
||||
Comment string `structs:"comment" json:"comment,omitempty"`
|
||||
SongCount int `structs:"song_count" json:"songCount"`
|
||||
Duration float32 `structs:"duration" json:"duration"`
|
||||
Size int64 `structs:"size" json:"size"`
|
||||
Genre string `structs:"genre" json:"genre"`
|
||||
Genres Genres `structs:"-" json:"genres"`
|
||||
FullText string `structs:"full_text" json:"fullText"`
|
||||
SortAlbumName string `structs:"sort_album_name" json:"sortAlbumName,omitempty"`
|
||||
SortArtistName string `structs:"sort_artist_name" json:"sortArtistName,omitempty"`
|
||||
SortAlbumArtistName string `structs:"sort_album_artist_name" json:"sortAlbumArtistName,omitempty"`
|
||||
OrderAlbumName string `structs:"order_album_name" json:"orderAlbumName"`
|
||||
OrderAlbumArtistName string `structs:"order_album_artist_name" json:"orderAlbumArtistName"`
|
||||
CatalogNum string `structs:"catalog_num" json:"catalogNum,omitempty"`
|
||||
MbzAlbumID string `structs:"mbz_album_id" json:"mbzAlbumId,omitempty" orm:"column(mbz_album_id)"`
|
||||
MbzAlbumArtistID string `structs:"mbz_album_artist_id" json:"mbzAlbumArtistId,omitempty" orm:"column(mbz_album_artist_id)"`
|
||||
MbzAlbumType string `structs:"mbz_album_type" json:"mbzAlbumType,omitempty"`
|
||||
MbzAlbumComment string `structs:"mbz_album_comment" json:"mbzAlbumComment,omitempty"`
|
||||
CreatedAt time.Time `structs:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `structs:"updated_at" json:"updatedAt"`
|
||||
}
|
||||
|
||||
type Albums []Album
|
||||
|
|
|
@ -3,11 +3,11 @@ package model
|
|||
import "time"
|
||||
|
||||
type Annotations struct {
|
||||
PlayCount int64 `json:"playCount"`
|
||||
PlayDate time.Time `json:"playDate"`
|
||||
Rating int `json:"rating"`
|
||||
Starred bool `json:"starred"`
|
||||
StarredAt time.Time `json:"starredAt"`
|
||||
PlayCount int64 `structs:"-" json:"playCount"`
|
||||
PlayDate time.Time `structs:"-" json:"playDate" `
|
||||
Rating int `structs:"-" json:"rating" `
|
||||
Starred bool `structs:"-" json:"starred" `
|
||||
StarredAt time.Time `structs:"-" json:"starredAt"`
|
||||
}
|
||||
|
||||
type AnnotatedModel interface {
|
||||
|
@ -19,7 +19,3 @@ type AnnotatedRepository interface {
|
|||
SetStar(starred bool, itemIDs ...string) error
|
||||
SetRating(rating int, itemID string) error
|
||||
}
|
||||
|
||||
// While I can't find a better way to make these fields optional in the models, I keep this list here
|
||||
// to be used in other packages
|
||||
var AnnotationFields = []string{"playCount", "playDate", "rating", "starred", "starredAt"}
|
||||
|
|
|
@ -3,25 +3,25 @@ package model
|
|||
import "time"
|
||||
|
||||
type Artist struct {
|
||||
Annotations
|
||||
Annotations `structs:"-"`
|
||||
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
Name string `json:"name"`
|
||||
AlbumCount int `json:"albumCount"`
|
||||
SongCount int `json:"songCount"`
|
||||
Genres Genres `json:"genres"`
|
||||
FullText string `json:"fullText"`
|
||||
SortArtistName string `json:"sortArtistName,omitempty"`
|
||||
OrderArtistName string `json:"orderArtistName"`
|
||||
Size int64 `json:"size"`
|
||||
MbzArtistID string `json:"mbzArtistId,omitempty" orm:"column(mbz_artist_id)"`
|
||||
Biography string `json:"biography,omitempty"`
|
||||
SmallImageUrl string `json:"smallImageUrl,omitempty"`
|
||||
MediumImageUrl string `json:"mediumImageUrl,omitempty"`
|
||||
LargeImageUrl string `json:"largeImageUrl,omitempty"`
|
||||
ExternalUrl string `json:"externalUrl,omitempty" orm:"column(external_url)"`
|
||||
SimilarArtists Artists `json:"-" orm:"-"`
|
||||
ExternalInfoUpdatedAt time.Time `json:"externalInfoUpdatedAt"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
Name string `structs:"name" json:"name"`
|
||||
AlbumCount int `structs:"album_count" json:"albumCount"`
|
||||
SongCount int `structs:"song_count" json:"songCount"`
|
||||
Genres Genres `structs:"-" json:"genres"`
|
||||
FullText string `structs:"full_text" json:"fullText"`
|
||||
SortArtistName string `structs:"sort_artist_name" json:"sortArtistName,omitempty"`
|
||||
OrderArtistName string `structs:"order_artist_name" json:"orderArtistName"`
|
||||
Size int64 `structs:"size" json:"size"`
|
||||
MbzArtistID string `structs:"mbz_artist_id" json:"mbzArtistId,omitempty" orm:"column(mbz_artist_id)"`
|
||||
Biography string `structs:"biography" json:"biography,omitempty"`
|
||||
SmallImageUrl string `structs:"small_image_url" json:"smallImageUrl,omitempty"`
|
||||
MediumImageUrl string `structs:"medium_image_url" json:"mediumImageUrl,omitempty"`
|
||||
LargeImageUrl string `structs:"large_image_url" json:"largeImageUrl,omitempty"`
|
||||
ExternalUrl string `structs:"external_url" json:"externalUrl,omitempty" orm:"column(external_url)"`
|
||||
SimilarArtists Artists `structs:"-" json:"-" orm:"-"`
|
||||
ExternalInfoUpdatedAt time.Time `structs:"external_info_updated_at" json:"externalInfoUpdatedAt"`
|
||||
}
|
||||
|
||||
func (a Artist) ArtistImageUrl() string {
|
||||
|
|
|
@ -3,7 +3,7 @@ package model
|
|||
import "time"
|
||||
|
||||
type Bookmarkable struct {
|
||||
BookmarkPosition int64 `json:"bookmarkPosition"`
|
||||
BookmarkPosition int64 `structs:"-" json:"bookmarkPosition"`
|
||||
}
|
||||
|
||||
type BookmarkableRepository interface {
|
||||
|
@ -13,16 +13,12 @@ type BookmarkableRepository interface {
|
|||
}
|
||||
|
||||
type Bookmark struct {
|
||||
Item MediaFile `json:"item"`
|
||||
Comment string `json:"comment"`
|
||||
Position int64 `json:"position"`
|
||||
ChangedBy string `json:"changed_by"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Item MediaFile `structs:"item" json:"item"`
|
||||
Comment string `structs:"comment" json:"comment"`
|
||||
Position int64 `structs:"position" json:"position"`
|
||||
ChangedBy string `structs:"changed_by" json:"changed_by"`
|
||||
CreatedAt time.Time `structs:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `structs:"updated_at" json:"updatedAt"`
|
||||
}
|
||||
|
||||
type Bookmarks []Bookmark
|
||||
|
||||
// While I can't find a better way to make these fields optional in the models, I keep this list here
|
||||
// to be used in other packages
|
||||
var BookmarkFields = []string{"bookmarkPosition"}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package model
|
||||
|
||||
type Genre struct {
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
Name string `json:"name"`
|
||||
SongCount int `json:"-"`
|
||||
AlbumCount int `json:"-"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
Name string `structs:"name" json:"name"`
|
||||
SongCount int `structs:"-" json:"-"`
|
||||
AlbumCount int `structs:"-" json:"-"`
|
||||
}
|
||||
|
||||
type Genres []Genre
|
||||
|
|
|
@ -6,50 +6,50 @@ import (
|
|||
)
|
||||
|
||||
type MediaFile struct {
|
||||
Annotations
|
||||
Bookmarkable
|
||||
Annotations `structs:"-"`
|
||||
Bookmarkable `structs:"-"`
|
||||
|
||||
ID string `json:"id" orm:"pk;column(id)"`
|
||||
Path string `json:"path"`
|
||||
Title string `json:"title"`
|
||||
Album string `json:"album"`
|
||||
ArtistID string `json:"artistId" orm:"pk;column(artist_id)"`
|
||||
Artist string `json:"artist"`
|
||||
AlbumArtistID string `json:"albumArtistId" orm:"pk;column(album_artist_id)"`
|
||||
AlbumArtist string `json:"albumArtist"`
|
||||
AlbumID string `json:"albumId" orm:"pk;column(album_id)"`
|
||||
HasCoverArt bool `json:"hasCoverArt"`
|
||||
TrackNumber int `json:"trackNumber"`
|
||||
DiscNumber int `json:"discNumber"`
|
||||
DiscSubtitle string `json:"discSubtitle,omitempty"`
|
||||
Year int `json:"year"`
|
||||
Size int64 `json:"size"`
|
||||
Suffix string `json:"suffix"`
|
||||
Duration float32 `json:"duration"`
|
||||
BitRate int `json:"bitRate"`
|
||||
Genre string `json:"genre"`
|
||||
Genres Genres `json:"genres"`
|
||||
FullText string `json:"fullText"`
|
||||
SortTitle string `json:"sortTitle,omitempty"`
|
||||
SortAlbumName string `json:"sortAlbumName,omitempty"`
|
||||
SortArtistName string `json:"sortArtistName,omitempty"`
|
||||
SortAlbumArtistName string `json:"sortAlbumArtistName,omitempty"`
|
||||
OrderAlbumName string `json:"orderAlbumName"`
|
||||
OrderArtistName string `json:"orderArtistName"`
|
||||
OrderAlbumArtistName string `json:"orderAlbumArtistName"`
|
||||
Compilation bool `json:"compilation"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
Lyrics string `json:"lyrics,omitempty"`
|
||||
Bpm int `json:"bpm,omitempty"`
|
||||
CatalogNum string `json:"catalogNum,omitempty"`
|
||||
MbzTrackID string `json:"mbzTrackId,omitempty" orm:"column(mbz_track_id)"`
|
||||
MbzAlbumID string `json:"mbzAlbumId,omitempty" orm:"column(mbz_album_id)"`
|
||||
MbzArtistID string `json:"mbzArtistId,omitempty" orm:"column(mbz_artist_id)"`
|
||||
MbzAlbumArtistID string `json:"mbzAlbumArtistId,omitempty" orm:"column(mbz_album_artist_id)"`
|
||||
MbzAlbumType string `json:"mbzAlbumType,omitempty"`
|
||||
MbzAlbumComment string `json:"mbzAlbumComment,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"` // Time this entry was created in the DB
|
||||
UpdatedAt time.Time `json:"updatedAt"` // Time of file last update (mtime)
|
||||
ID string `structs:"id" json:"id" orm:"pk;column(id)"`
|
||||
Path string `structs:"path" json:"path"`
|
||||
Title string `structs:"title" json:"title"`
|
||||
Album string `structs:"album" json:"album"`
|
||||
ArtistID string `structs:"artist_id" json:"artistId" orm:"pk;column(artist_id)"`
|
||||
Artist string `structs:"artist" json:"artist"`
|
||||
AlbumArtistID string `structs:"album_artist_id" json:"albumArtistId" orm:"pk;column(album_artist_id)"`
|
||||
AlbumArtist string `structs:"album_artist" json:"albumArtist"`
|
||||
AlbumID string `structs:"album_id" json:"albumId" orm:"pk;column(album_id)"`
|
||||
HasCoverArt bool `structs:"has_cover_art" json:"hasCoverArt"`
|
||||
TrackNumber int `structs:"track_number" json:"trackNumber"`
|
||||
DiscNumber int `structs:"disc_number" json:"discNumber"`
|
||||
DiscSubtitle string `structs:"disc_subtitle" json:"discSubtitle,omitempty"`
|
||||
Year int `structs:"year" json:"year"`
|
||||
Size int64 `structs:"size" json:"size"`
|
||||
Suffix string `structs:"suffix" json:"suffix"`
|
||||
Duration float32 `structs:"duration" json:"duration"`
|
||||
BitRate int `structs:"bit_rate" json:"bitRate"`
|
||||
Genre string `structs:"genre" json:"genre"`
|
||||
Genres Genres `structs:"-" json:"genres"`
|
||||
FullText string `structs:"full_text" json:"fullText"`
|
||||
SortTitle string `structs:"sort_title" json:"sortTitle,omitempty"`
|
||||
SortAlbumName string `structs:"sort_album_name" json:"sortAlbumName,omitempty"`
|
||||
SortArtistName string `structs:"sort_artist_name" json:"sortArtistName,omitempty"`
|
||||
SortAlbumArtistName string `structs:"sort_album_artist_name" json:"sortAlbumArtistName,omitempty"`
|
||||
OrderAlbumName string `structs:"order_album_name" json:"orderAlbumName"`
|
||||
OrderArtistName string `structs:"order_artist_name" json:"orderArtistName"`
|
||||
OrderAlbumArtistName string `structs:"order_album_artist_name" json:"orderAlbumArtistName"`
|
||||
Compilation bool `structs:"compilation" json:"compilation"`
|
||||
Comment string `structs:"comment" json:"comment,omitempty"`
|
||||
Lyrics string `structs:"lyrics" json:"lyrics,omitempty"`
|
||||
Bpm int `structs:"bpm" json:"bpm,omitempty"`
|
||||
CatalogNum string `structs:"catalog_num" json:"catalogNum,omitempty"`
|
||||
MbzTrackID string `structs:"mbz_track_id" json:"mbzTrackId,omitempty" orm:"column(mbz_track_id)"`
|
||||
MbzAlbumID string `structs:"mbz_album_id" json:"mbzAlbumId,omitempty" orm:"column(mbz_album_id)"`
|
||||
MbzArtistID string `structs:"mbz_artist_id" json:"mbzArtistId,omitempty" orm:"column(mbz_artist_id)"`
|
||||
MbzAlbumArtistID string `structs:"mbz_album_artist_id" json:"mbzAlbumArtistId,omitempty" orm:"column(mbz_album_artist_id)"`
|
||||
MbzAlbumType string `structs:"mbz_album_type" json:"mbzAlbumType,omitempty"`
|
||||
MbzAlbumComment string `structs:"mbz_album_comment" json:"mbzAlbumComment,omitempty"`
|
||||
CreatedAt time.Time `structs:"created_at" json:"createdAt"` // Time this entry was created in the DB
|
||||
UpdatedAt time.Time `structs:"updated_at" json:"updatedAt"` // Time of file last update (mtime)
|
||||
}
|
||||
|
||||
func (mf *MediaFile) ContentType() string {
|
||||
|
|
|
@ -5,17 +5,17 @@ import (
|
|||
)
|
||||
|
||||
type Player struct {
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
Name string `json:"name"`
|
||||
UserAgent string `json:"userAgent"`
|
||||
UserName string `json:"userName"`
|
||||
Client string `json:"client"`
|
||||
IPAddress string `json:"ipAddress"`
|
||||
LastSeen time.Time `json:"lastSeen"`
|
||||
TranscodingId string `json:"transcodingId"`
|
||||
MaxBitRate int `json:"maxBitRate"`
|
||||
ReportRealPath bool `json:"reportRealPath"`
|
||||
ScrobbleEnabled bool `json:"scrobbleEnabled"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
Name string `structs:"name" json:"name"`
|
||||
UserAgent string `structs:"user_agent" json:"userAgent"`
|
||||
UserName string `structs:"user_name" json:"userName"`
|
||||
Client string `structs:"client" json:"client"`
|
||||
IPAddress string `structs:"ip_address" json:"ipAddress"`
|
||||
LastSeen time.Time `structs:"last_seen" json:"lastSeen"`
|
||||
TranscodingId string `structs:"transcoding_id" json:"transcodingId"`
|
||||
MaxBitRate int `structs:"max_bit_rate" json:"maxBitRate"`
|
||||
ReportRealPath bool `structs:"report_real_path" json:"reportRealPath"`
|
||||
ScrobbleEnabled bool `structs:"scrobble_enabled" json:"scrobbleEnabled"`
|
||||
}
|
||||
|
||||
type Players []Player
|
||||
|
|
|
@ -5,19 +5,19 @@ import (
|
|||
)
|
||||
|
||||
type Playlist struct {
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
Name string `json:"name"`
|
||||
Comment string `json:"comment"`
|
||||
Duration float32 `json:"duration"`
|
||||
Size int64 `json:"size"`
|
||||
SongCount int `json:"songCount"`
|
||||
Owner string `json:"owner"`
|
||||
Public bool `json:"public"`
|
||||
Tracks MediaFiles `json:"tracks,omitempty"`
|
||||
Path string `json:"path"`
|
||||
Sync bool `json:"sync"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
Name string `structs:"name" json:"name"`
|
||||
Comment string `structs:"comment" json:"comment"`
|
||||
Duration float32 `structs:"duration" json:"duration"`
|
||||
Size int64 `structs:"size" json:"size"`
|
||||
SongCount int `structs:"song_count" json:"songCount"`
|
||||
Owner string `structs:"owner" json:"owner"`
|
||||
Public bool `structs:"public" json:"public"`
|
||||
Tracks MediaFiles `structs:"-" json:"tracks,omitempty"`
|
||||
Path string `structs:"path" json:"path"`
|
||||
Sync bool `structs:"sync" json:"sync"`
|
||||
CreatedAt time.Time `structs:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `structs:"updated_at" json:"updatedAt"`
|
||||
}
|
||||
|
||||
type Playlists []Playlist
|
||||
|
|
|
@ -5,14 +5,14 @@ import (
|
|||
)
|
||||
|
||||
type PlayQueue struct {
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
UserID string `json:"userId" orm:"column(user_id)"`
|
||||
Current string `json:"current"`
|
||||
Position int64 `json:"position"`
|
||||
ChangedBy string `json:"changedBy"`
|
||||
Items MediaFiles `json:"items,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
UserID string `structs:"user_id" json:"userId" orm:"column(user_id)"`
|
||||
Current string `structs:"current" json:"current"`
|
||||
Position int64 `structs:"position" json:"position"`
|
||||
ChangedBy string `structs:"changed_by" json:"changedBy"`
|
||||
Items MediaFiles `structs:"-" json:"items,omitempty"`
|
||||
CreatedAt time.Time `structs:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `structs:"updated_at" json:"updatedAt"`
|
||||
}
|
||||
|
||||
type PlayQueues []PlayQueue
|
||||
|
|
|
@ -5,7 +5,7 @@ import "time"
|
|||
type ScrobbleEntry struct {
|
||||
MediaFile
|
||||
Service string
|
||||
UserID string `json:"user_id" orm:"column(user_id)"`
|
||||
UserID string `structs:"user_id" orm:"column(user_id)"`
|
||||
PlayTime time.Time
|
||||
EnqueueTime time.Time
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@ import (
|
|||
)
|
||||
|
||||
type Share struct {
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
ExpiresAt time.Time `json:"expiresAt"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
LastVisitedAt time.Time `json:"lastVisitedAt"`
|
||||
ResourceIDs string `json:"resourceIds" orm:"column(resource_ids)"`
|
||||
ResourceType string `json:"resourceType"`
|
||||
VisitCount int `json:"visitCount"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
Name string `structs:"name" json:"name"`
|
||||
Description string `structs:"description" json:"description"`
|
||||
ExpiresAt time.Time `structs:"expires_at" json:"expiresAt"`
|
||||
CreatedAt time.Time `structs:"created_at" json:"createdAt"`
|
||||
LastVisitedAt time.Time `structs:"last_visited_at" json:"lastVisitedAt"`
|
||||
ResourceIDs string `structs:"resource_ids" json:"resourceIds" orm:"column(resource_ids)"`
|
||||
ResourceType string `structs:"resource_type" json:"resourceType"`
|
||||
VisitCount int `structs:"visit_count" json:"visitCount"`
|
||||
}
|
||||
|
||||
type Shares []Share
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package model
|
||||
|
||||
type Transcoding struct {
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
Name string `json:"name"`
|
||||
TargetFormat string `json:"targetFormat"`
|
||||
Command string `json:"command"`
|
||||
DefaultBitRate int `json:"defaultBitRate"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
Name string `structs:"name" json:"name"`
|
||||
TargetFormat string `structs:"target_format" json:"targetFormat"`
|
||||
Command string `structs:"command" json:"command"`
|
||||
DefaultBitRate int `structs:"default_bit_rate" json:"defaultBitRate"`
|
||||
}
|
||||
|
||||
type Transcodings []Transcoding
|
||||
|
|
|
@ -3,23 +3,23 @@ package model
|
|||
import "time"
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id" orm:"column(id)"`
|
||||
UserName string `json:"userName"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
IsAdmin bool `json:"isAdmin"`
|
||||
LastLoginAt *time.Time `json:"lastLoginAt"`
|
||||
LastAccessAt *time.Time `json:"lastAccessAt"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
ID string `structs:"id" json:"id" orm:"column(id)"`
|
||||
UserName string `structs:"user_name" json:"userName"`
|
||||
Name string `structs:"name" json:"name"`
|
||||
Email string `structs:"email" json:"email"`
|
||||
IsAdmin bool `structs:"is_admin" json:"isAdmin"`
|
||||
LastLoginAt time.Time `structs:"last_login_at" json:"lastLoginAt"`
|
||||
LastAccessAt time.Time `structs:"last_access_at" json:"lastAccessAt"`
|
||||
CreatedAt time.Time `structs:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `structs:"updated_at" json:"updatedAt"`
|
||||
|
||||
// This is only available on the backend, and it is never sent over the wire
|
||||
Password string `json:"-"`
|
||||
Password string `structs:"-" json:"-"`
|
||||
// This is used to set or change a password when calling Put. If it is empty, the password is not changed.
|
||||
// It is received from the UI with the name "password"
|
||||
NewPassword string `json:"password,omitempty"`
|
||||
NewPassword string `structs:"password,omitempty" json:"password,omitempty"`
|
||||
// If changing the password, this is also required
|
||||
CurrentPassword string `json:"currentPassword,omitempty"`
|
||||
CurrentPassword string `structs:"current_password,omitempty" json:"currentPassword,omitempty"`
|
||||
}
|
||||
|
||||
type Users []User
|
||||
|
|
|
@ -110,14 +110,11 @@ func (r *albumRepository) Get(id string) (*model.Album, error) {
|
|||
}
|
||||
|
||||
func (r *albumRepository) Put(m *model.Album) error {
|
||||
genres := m.Genres
|
||||
m.Genres = nil
|
||||
defer func() { m.Genres = genres }()
|
||||
_, err := r.put(m.ID, m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return r.updateGenres(m.ID, r.tableName, genres)
|
||||
return r.updateGenres(m.ID, r.tableName, m.Genres)
|
||||
}
|
||||
|
||||
func (r *albumRepository) GetAll(options ...model.QueryOptions) (model.Albums, error) {
|
||||
|
|
|
@ -23,8 +23,8 @@ type artistRepository struct {
|
|||
}
|
||||
|
||||
type dbArtist struct {
|
||||
model.Artist
|
||||
SimilarArtists string `json:"similarArtists"`
|
||||
model.Artist `structs:",flatten"`
|
||||
SimilarArtists string `structs:"similar_artists" json:"similarArtists"`
|
||||
}
|
||||
|
||||
func NewArtistRepository(ctx context.Context, o orm.Ormer) model.ArtistRepository {
|
||||
|
@ -60,16 +60,13 @@ func (r *artistRepository) Exists(id string) (bool, error) {
|
|||
}
|
||||
|
||||
func (r *artistRepository) Put(a *model.Artist) error {
|
||||
genres := a.Genres
|
||||
a.Genres = nil
|
||||
defer func() { a.Genres = genres }()
|
||||
a.FullText = getFullText(a.Name, a.SortArtistName)
|
||||
dba := r.fromModel(a)
|
||||
_, err := r.put(dba.ID, dba)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return r.updateGenres(a.ID, r.tableName, genres)
|
||||
return r.updateGenres(a.ID, r.tableName, a.Genres)
|
||||
}
|
||||
|
||||
func (r *artistRepository) Get(id string) (*model.Artist, error) {
|
||||
|
|
|
@ -2,38 +2,29 @@ package persistence
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/navidrome/navidrome/consts"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/utils"
|
||||
)
|
||||
|
||||
func toSqlArgs(rec interface{}) (map[string]interface{}, error) {
|
||||
// Convert to JSON...
|
||||
b, err := json.Marshal(rec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ... then convert to map
|
||||
var m map[string]interface{}
|
||||
err = json.Unmarshal(b, &m)
|
||||
r := make(map[string]interface{}, len(m))
|
||||
for f, v := range m {
|
||||
isAnnotationField := utils.StringInSlice(f, model.AnnotationFields)
|
||||
isBookmarkField := utils.StringInSlice(f, model.BookmarkFields)
|
||||
if !isAnnotationField && !isBookmarkField && v != nil {
|
||||
r[toSnakeCase(f)] = v
|
||||
m := structs.Map(rec)
|
||||
for k, v := range m {
|
||||
if t, ok := v.(time.Time); ok {
|
||||
m[k] = t.Format(time.RFC3339Nano)
|
||||
}
|
||||
if t, ok := v.(*time.Time); ok && t != nil {
|
||||
m[k] = t.Format(time.RFC3339Nano)
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)")
|
||||
|
|
|
@ -26,31 +26,26 @@ var _ = Describe("Helpers", func() {
|
|||
})
|
||||
})
|
||||
Describe("toSqlArgs", func() {
|
||||
type Embed struct{}
|
||||
type Model struct {
|
||||
ID string `json:"id"`
|
||||
AlbumId string `json:"albumId"`
|
||||
PlayCount int `json:"playCount"`
|
||||
CreatedAt *time.Time
|
||||
Embed `structs:"-"`
|
||||
ID string `structs:"id" json:"id"`
|
||||
AlbumId string `structs:"album_id" json:"albumId"`
|
||||
PlayCount int `structs:"play_count" json:"playCount"`
|
||||
UpdatedAt *time.Time `structs:"updated_at"`
|
||||
CreatedAt time.Time `structs:"created_at"`
|
||||
}
|
||||
|
||||
It("returns a map with snake_case keys", func() {
|
||||
now := time.Now()
|
||||
m := &Model{ID: "123", AlbumId: "456", CreatedAt: &now, PlayCount: 2}
|
||||
m := &Model{ID: "123", AlbumId: "456", CreatedAt: now, UpdatedAt: &now, PlayCount: 2}
|
||||
args, err := toSqlArgs(m)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(args).To(HaveKeyWithValue("id", "123"))
|
||||
Expect(args).To(HaveKeyWithValue("album_id", "456"))
|
||||
Expect(args).To(HaveKey("created_at"))
|
||||
Expect(args).To(HaveLen(3))
|
||||
})
|
||||
|
||||
It("remove null fields", func() {
|
||||
m := &Model{ID: "123", AlbumId: "456"}
|
||||
args, err := toSqlArgs(m)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(args).To(HaveKey("id"))
|
||||
Expect(args).To(HaveKey("album_id"))
|
||||
Expect(args).To(HaveLen(2))
|
||||
Expect(args).To(HaveKeyWithValue("updated_at", now.Format(time.RFC3339Nano)))
|
||||
Expect(args).To(HaveKeyWithValue("created_at", now.Format(time.RFC3339Nano)))
|
||||
Expect(args).ToNot(HaveKey("Embed"))
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -51,14 +51,11 @@ func (r *mediaFileRepository) Exists(id string) (bool, error) {
|
|||
func (r *mediaFileRepository) Put(m *model.MediaFile) error {
|
||||
m.FullText = getFullText(m.Title, m.Album, m.Artist, m.AlbumArtist,
|
||||
m.SortTitle, m.SortAlbumName, m.SortArtistName, m.SortAlbumArtistName, m.DiscSubtitle)
|
||||
genres := m.Genres
|
||||
m.Genres = nil
|
||||
defer func() { m.Genres = genres }()
|
||||
_, err := r.put(m.ID, m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return r.updateGenres(m.ID, r.tableName, genres)
|
||||
return r.updateGenres(m.ID, r.tableName, m.Genres)
|
||||
}
|
||||
|
||||
func (r *mediaFileRepository) selectMediaFile(options ...model.QueryOptions) SelectBuilder {
|
||||
|
|
|
@ -25,14 +25,14 @@ func NewPlayQueueRepository(ctx context.Context, o orm.Ormer) model.PlayQueueRep
|
|||
}
|
||||
|
||||
type playQueue struct {
|
||||
ID string `orm:"column(id)"`
|
||||
UserID string `orm:"column(user_id)"`
|
||||
Current string
|
||||
Position int64
|
||||
ChangedBy string
|
||||
Items string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
ID string `structs:"id" orm:"column(id)"`
|
||||
UserID string `structs:"user_id" orm:"column(user_id)"`
|
||||
Current string `structs:"current"`
|
||||
Position int64 `structs:"position"`
|
||||
ChangedBy string `structs:"changed_by"`
|
||||
Items string `structs:"items"`
|
||||
CreatedAt time.Time `structs:"created_at"`
|
||||
UpdatedAt time.Time `structs:"updated_at"`
|
||||
}
|
||||
|
||||
func (r *playQueueRepository) Store(q *model.PlayQueue) error {
|
||||
|
|
|
@ -142,7 +142,7 @@ func createAdminUser(ctx context.Context, ds model.DataStore, username, password
|
|||
Email: "",
|
||||
NewPassword: password,
|
||||
IsAdmin: true,
|
||||
LastLoginAt: &now,
|
||||
LastLoginAt: now,
|
||||
}
|
||||
err := ds.User(ctx).Put(&initialUser)
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue