use references when possible
This commit is contained in:
@@ -8,14 +8,11 @@ issues:
|
||||
exclude-rules:
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocyclo
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
- text: "weak cryptographic primitive"
|
||||
linters:
|
||||
- gosec
|
||||
- path: model/model.go
|
||||
- path: model/model\.go
|
||||
linters:
|
||||
- lll
|
||||
- path: server/handler/
|
||||
|
||||
@@ -10,16 +10,16 @@ import (
|
||||
type Artist struct {
|
||||
IDBase
|
||||
Name string `gorm:"not null; unique_index"`
|
||||
Albums []Album `gorm:"foreignkey:TagArtistID"`
|
||||
Albums []*Album `gorm:"foreignkey:TagArtistID"`
|
||||
}
|
||||
|
||||
type Track struct {
|
||||
IDBase
|
||||
CrudBase
|
||||
Album Album
|
||||
Album *Album
|
||||
AlbumID int `gorm:"not null; unique_index:idx_folder_filename" sql:"default: null; type:int REFERENCES albums(id) ON DELETE CASCADE"`
|
||||
Filename string `gorm:"not null; unique_index:idx_folder_filename" sql:"default: null"`
|
||||
Artist Artist
|
||||
Artist *Artist
|
||||
ArtistID int `gorm:"not null; index" sql:"default: null; type:int REFERENCES artists(id) ON DELETE CASCADE"`
|
||||
Duration int `gorm:"not null" sql:"default: null"`
|
||||
Size int `gorm:"not null" sql:"default: null"`
|
||||
@@ -63,9 +63,9 @@ type Setting struct {
|
||||
|
||||
type Play struct {
|
||||
IDBase
|
||||
User User
|
||||
User *User
|
||||
UserID int `gorm:"not null; index" sql:"default: null; type:int REFERENCES users(id) ON DELETE CASCADE"`
|
||||
Album Album
|
||||
Album *Album
|
||||
AlbumID int `gorm:"not null; index" sql:"default: null; type:int REFERENCES albums(id) ON DELETE CASCADE"`
|
||||
Time time.Time `sql:"default: null"`
|
||||
Count int
|
||||
@@ -79,10 +79,10 @@ type Album struct {
|
||||
Parent *Album
|
||||
ParentID int `sql:"default: null; type:int REFERENCES albums(id) ON DELETE CASCADE"`
|
||||
Cover string `sql:"default: null"`
|
||||
TagArtist Artist
|
||||
TagArtist *Artist
|
||||
TagArtistID int `gorm:"index" sql:"default: null; type:int REFERENCES artists(id) ON DELETE CASCADE"`
|
||||
TagTitle string `gorm:"index" sql:"default: null"`
|
||||
TagYear int `sql:"default: null"`
|
||||
Tracks []Track
|
||||
Tracks []*Track
|
||||
IsNew bool `gorm:"-"`
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (s *Scanner) callbackPost(fullPath string, info *godirwalk.Dirent) error {
|
||||
if folder.IsNew {
|
||||
folder.ParentID = s.curFolderID()
|
||||
folder.Cover = s.curCover
|
||||
s.tx.Save(&folder)
|
||||
s.tx.Save(folder)
|
||||
}
|
||||
s.curCover = ""
|
||||
log.Printf("processed folder `%s`\n", fullPath)
|
||||
@@ -66,42 +66,45 @@ func (s *Scanner) callbackPost(fullPath string, info *godirwalk.Dirent) error {
|
||||
}
|
||||
|
||||
func (s *Scanner) handleFolder(it *item) error {
|
||||
var folder model.Album
|
||||
folder := &model.Album{}
|
||||
defer s.curFolders.Push(folder)
|
||||
err := s.tx.
|
||||
Where(model.Album{
|
||||
LeftPath: it.directory,
|
||||
RightPath: it.filename,
|
||||
}).
|
||||
First(&folder).
|
||||
First(folder).
|
||||
Error
|
||||
if !gorm.IsRecordNotFoundError(err) &&
|
||||
it.stat.ModTime().Before(folder.UpdatedAt) {
|
||||
// we found the record but it hasn't changed
|
||||
s.curFolders.Push(&folder)
|
||||
return nil
|
||||
}
|
||||
folder.LeftPath = it.directory
|
||||
folder.RightPath = it.filename
|
||||
s.tx.Save(&folder)
|
||||
s.tx.Save(folder)
|
||||
folder.IsNew = true
|
||||
s.curFolders.Push(&folder)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Scanner) handleTrack(it *item) error {
|
||||
//
|
||||
// set track basics
|
||||
var track model.Track
|
||||
track := &model.Track{}
|
||||
defer func() {
|
||||
// id will will be found (the first early return)
|
||||
// or created the tx.Save(track)
|
||||
s.seenTracks[track.ID] = struct{}{}
|
||||
}()
|
||||
err := s.tx.
|
||||
Where(model.Track{
|
||||
AlbumID: s.curFolderID(),
|
||||
Filename: it.filename,
|
||||
}).
|
||||
First(&track).
|
||||
First(track).
|
||||
Error
|
||||
if !gorm.IsRecordNotFoundError(err) &&
|
||||
it.stat.ModTime().Before(track.UpdatedAt) {
|
||||
s.seenTracks[track.ID] = struct{}{}
|
||||
// we found the record but it hasn't changed
|
||||
return nil
|
||||
}
|
||||
@@ -125,18 +128,17 @@ func (s *Scanner) handleTrack(it *item) error {
|
||||
track.TagYear = tags.Year()
|
||||
//
|
||||
// set album artist basics
|
||||
var artist model.Artist
|
||||
artist := &model.Artist{}
|
||||
err = s.tx.
|
||||
Where("name = ?", tags.AlbumArtist()).
|
||||
First(&artist).
|
||||
First(artist).
|
||||
Error
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
artist.Name = tags.AlbumArtist()
|
||||
s.tx.Save(&artist)
|
||||
s.tx.Save(artist)
|
||||
}
|
||||
track.ArtistID = artist.ID
|
||||
s.tx.Save(&track)
|
||||
s.seenTracks[track.ID] = struct{}{}
|
||||
s.tx.Save(track)
|
||||
//
|
||||
// set album if this is the first track in the folder
|
||||
if !s.curFolder().IsNew {
|
||||
|
||||
@@ -8,14 +8,17 @@ import (
|
||||
)
|
||||
|
||||
func makeAlbumFromAlbum(a *model.Album, artist *model.Artist) *subsonic.Album {
|
||||
return &subsonic.Album{
|
||||
ret := &subsonic.Album{
|
||||
ID: a.ID,
|
||||
Name: a.TagTitle,
|
||||
Created: a.CreatedAt,
|
||||
CoverID: a.ID,
|
||||
Artist: artist.Name,
|
||||
ArtistID: artist.ID,
|
||||
}
|
||||
if artist != nil {
|
||||
ret.Artist = artist.Name
|
||||
ret.ArtistID = artist.ID
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func makeTrackFromTrack(t *model.Track, album *model.Album) *subsonic.Track {
|
||||
|
||||
@@ -24,10 +24,10 @@ type Controller struct {
|
||||
}
|
||||
|
||||
func (c *Controller) GetSetting(key string) string {
|
||||
var setting model.Setting
|
||||
setting := &model.Setting{}
|
||||
c.DB.
|
||||
Where("key = ?", key).
|
||||
First(&setting)
|
||||
First(setting)
|
||||
return setting.Value
|
||||
}
|
||||
|
||||
@@ -39,13 +39,13 @@ func (c *Controller) SetSetting(key, value string) {
|
||||
}
|
||||
|
||||
func (c *Controller) GetUserFromName(name string) *model.User {
|
||||
var user model.User
|
||||
user := &model.User{}
|
||||
err := c.DB.
|
||||
Where("name = ?", name).
|
||||
First(&user).
|
||||
First(user).
|
||||
Error
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
return nil
|
||||
}
|
||||
return &user
|
||||
return user
|
||||
}
|
||||
|
||||
@@ -48,11 +48,11 @@ func (c *Controller) ServeLogout(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (c *Controller) ServeHome(w http.ResponseWriter, r *http.Request) {
|
||||
var data templateData
|
||||
c.DB.Table("artists").Count(&data.ArtistCount)
|
||||
c.DB.Table("albums").Count(&data.AlbumCount)
|
||||
c.DB.Table("tracks").Count(&data.TrackCount)
|
||||
c.DB.Find(&data.AllUsers)
|
||||
data := &templateData{}
|
||||
c.DB.Table("artists").Count(data.ArtistCount)
|
||||
c.DB.Table("albums").Count(data.AlbumCount)
|
||||
c.DB.Table("tracks").Count(data.TrackCount)
|
||||
c.DB.Find(data.AllUsers)
|
||||
data.CurrentLastFMAPIKey = c.GetSetting("lastfm_api_key")
|
||||
scheme := firstExisting(
|
||||
"http", // fallback
|
||||
@@ -66,7 +66,7 @@ func (c *Controller) ServeHome(w http.ResponseWriter, r *http.Request) {
|
||||
r.Host,
|
||||
)
|
||||
data.RequestRoot = fmt.Sprintf("%s://%s", scheme, host)
|
||||
renderTemplate(w, r, c.Templates["home"], &data)
|
||||
renderTemplate(w, r, c.Templates["home"], data)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeChangeOwnPassword(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -127,27 +127,27 @@ func (c *Controller) ServeChangePassword(w http.ResponseWriter, r *http.Request)
|
||||
http.Error(w, "please provide a username", 400)
|
||||
return
|
||||
}
|
||||
var user model.User
|
||||
user := &model.User{}
|
||||
err := c.DB.
|
||||
Where("name = ?", username).
|
||||
First(&user).
|
||||
First(user).
|
||||
Error
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
http.Error(w, "couldn't find a user with that name", 400)
|
||||
return
|
||||
}
|
||||
var data templateData
|
||||
data.SelectedUser = &user
|
||||
renderTemplate(w, r, c.Templates["change_password"], &data)
|
||||
data := &templateData{}
|
||||
data.SelectedUser = user
|
||||
renderTemplate(w, r, c.Templates["change_password"], data)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeChangePasswordDo(w http.ResponseWriter, r *http.Request) {
|
||||
session := r.Context().Value(contextSessionKey).(*sessions.Session)
|
||||
username := r.URL.Query().Get("user")
|
||||
var user model.User
|
||||
user := &model.User{}
|
||||
c.DB.
|
||||
Where("name = ?", username).
|
||||
First(&user)
|
||||
First(user)
|
||||
passwordOne := r.FormValue("password_one")
|
||||
passwordTwo := r.FormValue("password_two")
|
||||
err := validatePasswords(passwordOne, passwordTwo)
|
||||
@@ -158,7 +158,7 @@ func (c *Controller) ServeChangePasswordDo(w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
user.Password = passwordOne
|
||||
c.DB.Save(&user)
|
||||
c.DB.Save(user)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
@@ -168,27 +168,27 @@ func (c *Controller) ServeDeleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "please provide a username", 400)
|
||||
return
|
||||
}
|
||||
var user model.User
|
||||
user := &model.User{}
|
||||
err := c.DB.
|
||||
Where("name = ?", username).
|
||||
First(&user).
|
||||
First(user).
|
||||
Error
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
http.Error(w, "couldn't find a user with that name", 400)
|
||||
return
|
||||
}
|
||||
var data templateData
|
||||
data.SelectedUser = &user
|
||||
renderTemplate(w, r, c.Templates["delete_user"], &data)
|
||||
data := &templateData{}
|
||||
data.SelectedUser = user
|
||||
renderTemplate(w, r, c.Templates["delete_user"], data)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeDeleteUserDo(w http.ResponseWriter, r *http.Request) {
|
||||
username := r.URL.Query().Get("user")
|
||||
var user model.User
|
||||
user := &model.User{}
|
||||
c.DB.
|
||||
Where("name = ?", username).
|
||||
First(&user)
|
||||
c.DB.Delete(&user)
|
||||
First(user)
|
||||
c.DB.Delete(user)
|
||||
http.Redirect(w, r, "/admin/home", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
@@ -232,10 +232,10 @@ func (c *Controller) ServeCreateUserDo(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (c *Controller) ServeUpdateLastFMAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
var data templateData
|
||||
data := &templateData{}
|
||||
data.CurrentLastFMAPIKey = c.GetSetting("lastfm_api_key")
|
||||
data.CurrentLastFMAPISecret = c.GetSetting("lastfm_secret")
|
||||
renderTemplate(w, r, c.Templates["update_lastfm_api_key"], &data)
|
||||
renderTemplate(w, r, c.Templates["update_lastfm_api_key"], data)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeUpdateLastFMAPIKeyDo(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -19,12 +19,12 @@ import (
|
||||
// under the root directory
|
||||
|
||||
func (c *Controller) GetIndexes(w http.ResponseWriter, r *http.Request) {
|
||||
var folders []model.Album
|
||||
var folders []*model.Album
|
||||
c.DB.
|
||||
Where("parent_id = 1").
|
||||
Find(&folders)
|
||||
var indexMap = make(map[rune]*subsonic.Index)
|
||||
var indexes []*subsonic.Index
|
||||
indexMap := make(map[rune]*subsonic.Index)
|
||||
indexes := []*subsonic.Index{}
|
||||
for _, folder := range folders {
|
||||
i := indexOf(folder.RightPath)
|
||||
index, ok := indexMap[i]
|
||||
@@ -37,7 +37,7 @@ func (c *Controller) GetIndexes(w http.ResponseWriter, r *http.Request) {
|
||||
indexes = append(indexes, index)
|
||||
}
|
||||
index.Artists = append(index.Artists,
|
||||
makeArtistFromFolder(&folder))
|
||||
makeArtistFromFolder(folder))
|
||||
}
|
||||
sort.Slice(indexes, func(i, j int) bool {
|
||||
return indexes[i].Name < indexes[j].Name
|
||||
@@ -57,28 +57,28 @@ func (c *Controller) GetMusicDirectory(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
childrenObj := []*subsonic.Track{}
|
||||
var folder model.Album
|
||||
c.DB.First(&folder, id)
|
||||
folder := &model.Album{}
|
||||
c.DB.First(folder, id)
|
||||
//
|
||||
// start looking for child childFolders in the current dir
|
||||
var childFolders []model.Album
|
||||
var childFolders []*model.Album
|
||||
c.DB.
|
||||
Where("parent_id = ?", id).
|
||||
Find(&childFolders)
|
||||
for _, c := range childFolders {
|
||||
childrenObj = append(childrenObj,
|
||||
makeChildFromFolder(&c, &folder))
|
||||
makeChildFromFolder(c, folder))
|
||||
}
|
||||
//
|
||||
// start looking for child childTracks in the current dir
|
||||
var childTracks []model.Track
|
||||
var childTracks []*model.Track
|
||||
c.DB.
|
||||
Where("album_id = ?", id).
|
||||
Preload("Album").
|
||||
Order("filename").
|
||||
Find(&childTracks)
|
||||
for _, c := range childTracks {
|
||||
toAppend := makeChildFromTrack(&c, &folder)
|
||||
toAppend := makeChildFromTrack(c, folder)
|
||||
if getStrParam(r, "c") == "Jamstash" {
|
||||
// jamstash thinks it can't play flacs
|
||||
toAppend.ContentType = "audio/mpeg"
|
||||
@@ -89,7 +89,7 @@ func (c *Controller) GetMusicDirectory(w http.ResponseWriter, r *http.Request) {
|
||||
//
|
||||
// respond section
|
||||
sub := subsonic.NewResponse()
|
||||
sub.Directory = makeDirFromFolder(&folder, childrenObj)
|
||||
sub.Directory = makeDirFromFolder(folder, childrenObj)
|
||||
respond(w, r, sub)
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ func (c *Controller) GetAlbumList(w http.ResponseWriter, r *http.Request) {
|
||||
"unknown value `%s` for parameter 'type'", listType)
|
||||
return
|
||||
}
|
||||
var folders []model.Album
|
||||
var folders []*model.Album
|
||||
q.
|
||||
Where("albums.tag_artist_id IS NOT NULL").
|
||||
Offset(getIntParamOr(r, "offset", 0)).
|
||||
@@ -144,7 +144,7 @@ func (c *Controller) GetAlbumList(w http.ResponseWriter, r *http.Request) {
|
||||
sub.Albums = &subsonic.Albums{}
|
||||
for _, folder := range folders {
|
||||
sub.Albums.List = append(sub.Albums.List,
|
||||
makeAlbumFromFolder(&folder))
|
||||
makeAlbumFromFolder(folder))
|
||||
}
|
||||
respond(w, r, sub)
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func (c *Controller) SearchTwo(w http.ResponseWriter, r *http.Request) {
|
||||
results := &subsonic.SearchResultTwo{}
|
||||
//
|
||||
// search "artists"
|
||||
var artists []model.Album
|
||||
var artists []*model.Album
|
||||
c.DB.
|
||||
Where("parent_id = 1 AND right_path LIKE ?", query).
|
||||
Offset(getIntParamOr(r, "artistOffset", 0)).
|
||||
@@ -168,11 +168,11 @@ func (c *Controller) SearchTwo(w http.ResponseWriter, r *http.Request) {
|
||||
Find(&artists)
|
||||
for _, a := range artists {
|
||||
results.Artists = append(results.Artists,
|
||||
makeDirFromFolder(&a, nil))
|
||||
makeDirFromFolder(a, nil))
|
||||
}
|
||||
//
|
||||
// search "albums"
|
||||
var albums []model.Album
|
||||
var albums []*model.Album
|
||||
c.DB.
|
||||
Preload("Parent").
|
||||
Where("tag_artist_id IS NOT NULL AND right_path LIKE ?", query).
|
||||
@@ -181,11 +181,11 @@ func (c *Controller) SearchTwo(w http.ResponseWriter, r *http.Request) {
|
||||
Find(&albums)
|
||||
for _, a := range albums {
|
||||
results.Albums = append(results.Albums,
|
||||
makeChildFromFolder(&a, a.Parent))
|
||||
makeChildFromFolder(a, a.Parent))
|
||||
}
|
||||
//
|
||||
// search tracks
|
||||
var tracks []model.Track
|
||||
var tracks []*model.Track
|
||||
c.DB.
|
||||
Preload("Album").
|
||||
Where("filename LIKE ?", query).
|
||||
@@ -194,7 +194,7 @@ func (c *Controller) SearchTwo(w http.ResponseWriter, r *http.Request) {
|
||||
Find(&tracks)
|
||||
for _, t := range tracks {
|
||||
results.Tracks = append(results.Tracks,
|
||||
makeChildFromTrack(&t, &t.Album))
|
||||
makeChildFromTrack(t, t.Album))
|
||||
}
|
||||
//
|
||||
sub := subsonic.NewResponse()
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
)
|
||||
|
||||
func (c *Controller) GetArtists(w http.ResponseWriter, r *http.Request) {
|
||||
var artists []model.Artist
|
||||
var artists []*model.Artist
|
||||
c.DB.Find(&artists)
|
||||
var indexMap = make(map[rune]*subsonic.Index)
|
||||
var indexes subsonic.Artists
|
||||
indexMap := make(map[rune]*subsonic.Index)
|
||||
indexes := &subsonic.Artists{}
|
||||
for _, artist := range artists {
|
||||
i := indexOf(artist.Name)
|
||||
index, ok := indexMap[i]
|
||||
@@ -29,13 +29,13 @@ func (c *Controller) GetArtists(w http.ResponseWriter, r *http.Request) {
|
||||
indexes.List = append(indexes.List, index)
|
||||
}
|
||||
index.Artists = append(index.Artists,
|
||||
makeArtistFromArtist(&artist))
|
||||
makeArtistFromArtist(artist))
|
||||
}
|
||||
sort.Slice(indexes.List, func(i, j int) bool {
|
||||
return indexes.List[i].Name < indexes.List[j].Name
|
||||
})
|
||||
sub := subsonic.NewResponse()
|
||||
sub.Artists = &indexes
|
||||
sub.Artists = indexes
|
||||
respond(w, r, sub)
|
||||
}
|
||||
|
||||
@@ -45,15 +45,15 @@ func (c *Controller) GetArtist(w http.ResponseWriter, r *http.Request) {
|
||||
respondError(w, r, 10, "please provide an `id` parameter")
|
||||
return
|
||||
}
|
||||
var artist model.Artist
|
||||
artist := &model.Artist{}
|
||||
c.DB.
|
||||
Preload("Albums").
|
||||
First(&artist, id)
|
||||
First(artist, id)
|
||||
sub := subsonic.NewResponse()
|
||||
sub.Artist = makeArtistFromArtist(&artist)
|
||||
sub.Artist = makeArtistFromArtist(artist)
|
||||
for _, album := range artist.Albums {
|
||||
sub.Artist.Albums = append(sub.Artist.Albums,
|
||||
makeAlbumFromAlbum(&album, &artist))
|
||||
makeAlbumFromAlbum(album, artist))
|
||||
}
|
||||
respond(w, r, sub)
|
||||
}
|
||||
@@ -64,23 +64,23 @@ func (c *Controller) GetAlbum(w http.ResponseWriter, r *http.Request) {
|
||||
respondError(w, r, 10, "please provide an `id` parameter")
|
||||
return
|
||||
}
|
||||
var album model.Album
|
||||
album := &model.Album{}
|
||||
err = c.DB.
|
||||
Preload("TagArtist").
|
||||
Preload("Tracks", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Order("tracks.tag_track_number")
|
||||
}).
|
||||
First(&album, id).
|
||||
First(album, id).
|
||||
Error
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
respondError(w, r, 10, "couldn't find an album with that id")
|
||||
return
|
||||
}
|
||||
sub := subsonic.NewResponse()
|
||||
sub.Album = makeAlbumFromAlbum(&album, &album.TagArtist)
|
||||
sub.Album = makeAlbumFromAlbum(album, album.TagArtist)
|
||||
for _, track := range album.Tracks {
|
||||
sub.Album.Tracks = append(sub.Album.Tracks,
|
||||
makeTrackFromTrack(&track, &album))
|
||||
makeTrackFromTrack(track, album))
|
||||
}
|
||||
respond(w, r, sub)
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func (c *Controller) GetAlbumListTwo(w http.ResponseWriter, r *http.Request) {
|
||||
"unknown value `%s` for parameter 'type'", listType)
|
||||
return
|
||||
}
|
||||
var albums []model.Album
|
||||
var albums []*model.Album
|
||||
q.
|
||||
Where("albums.tag_artist_id IS NOT NULL").
|
||||
Offset(getIntParamOr(r, "offset", 0)).
|
||||
@@ -142,7 +142,7 @@ func (c *Controller) GetAlbumListTwo(w http.ResponseWriter, r *http.Request) {
|
||||
sub.AlbumsTwo = &subsonic.Albums{}
|
||||
for _, album := range albums {
|
||||
sub.AlbumsTwo.List = append(sub.AlbumsTwo.List,
|
||||
makeAlbumFromAlbum(&album, &album.TagArtist))
|
||||
makeAlbumFromAlbum(album, album.TagArtist))
|
||||
}
|
||||
respond(w, r, sub)
|
||||
}
|
||||
@@ -158,7 +158,7 @@ func (c *Controller) SearchThree(w http.ResponseWriter, r *http.Request) {
|
||||
results := &subsonic.SearchResultThree{}
|
||||
//
|
||||
// search "artists"
|
||||
var artists []model.Artist
|
||||
var artists []*model.Artist
|
||||
c.DB.
|
||||
Where("name LIKE ?", query).
|
||||
Offset(getIntParamOr(r, "artistOffset", 0)).
|
||||
@@ -166,11 +166,11 @@ func (c *Controller) SearchThree(w http.ResponseWriter, r *http.Request) {
|
||||
Find(&artists)
|
||||
for _, a := range artists {
|
||||
results.Artists = append(results.Artists,
|
||||
makeArtistFromArtist(&a))
|
||||
makeArtistFromArtist(a))
|
||||
}
|
||||
//
|
||||
// search "albums"
|
||||
var albums []model.Album
|
||||
var albums []*model.Album
|
||||
c.DB.
|
||||
Preload("TagArtist").
|
||||
Where("tag_title LIKE ?", query).
|
||||
@@ -179,11 +179,11 @@ func (c *Controller) SearchThree(w http.ResponseWriter, r *http.Request) {
|
||||
Find(&albums)
|
||||
for _, a := range albums {
|
||||
results.Albums = append(results.Albums,
|
||||
makeAlbumFromAlbum(&a, &a.TagArtist))
|
||||
makeAlbumFromAlbum(a, a.TagArtist))
|
||||
}
|
||||
//
|
||||
// search tracks
|
||||
var tracks []model.Track
|
||||
var tracks []*model.Track
|
||||
c.DB.
|
||||
Preload("Album").
|
||||
Where("tag_title LIKE ?", query).
|
||||
@@ -192,7 +192,7 @@ func (c *Controller) SearchThree(w http.ResponseWriter, r *http.Request) {
|
||||
Find(&tracks)
|
||||
for _, t := range tracks {
|
||||
results.Tracks = append(results.Tracks,
|
||||
makeTrackFromTrack(&t, &t.Album))
|
||||
makeTrackFromTrack(t, t.Album))
|
||||
}
|
||||
sub := subsonic.NewResponse()
|
||||
sub.SearchResultThree = results
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -32,10 +33,10 @@ func (c *Controller) Stream(w http.ResponseWriter, r *http.Request) {
|
||||
respondError(w, r, 10, "please provide an `id` parameter")
|
||||
return
|
||||
}
|
||||
var track model.Track
|
||||
track := &model.Track{}
|
||||
err = c.DB.
|
||||
Preload("Album").
|
||||
First(&track, id).
|
||||
First(track, id).
|
||||
Error
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
respondError(w, r, 70, "media with id `%d` was not found", id)
|
||||
@@ -75,10 +76,10 @@ func (c *Controller) GetCoverArt(w http.ResponseWriter, r *http.Request) {
|
||||
respondError(w, r, 10, "please provide an `id` parameter")
|
||||
return
|
||||
}
|
||||
var folder model.Album
|
||||
folder := &model.Album{}
|
||||
err = c.DB.
|
||||
Select("id, path, cover").
|
||||
First(&folder, id).
|
||||
First(folder, id).
|
||||
Error
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
respondError(w, r, 10, "could not find a cover with that id")
|
||||
@@ -123,17 +124,17 @@ func (c *Controller) Scrobble(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
// fetch track for getting info to send to last.fm function
|
||||
var track model.Track
|
||||
track := &model.Track{}
|
||||
c.DB.
|
||||
Preload("Album").
|
||||
Preload("Artist").
|
||||
First(&track, id)
|
||||
First(track, id)
|
||||
// scrobble with above info
|
||||
err = lastfm.Scrobble(
|
||||
c.GetSetting("lastfm_api_key"),
|
||||
c.GetSetting("lastfm_secret"),
|
||||
user.LastFMSession,
|
||||
&track,
|
||||
track,
|
||||
// clients will provide time in miliseconds, so use that or
|
||||
// instead convert UnixNano to miliseconds
|
||||
getIntParamOr(r, "time", int(time.Now().UnixNano()/1e6)),
|
||||
@@ -158,14 +159,22 @@ func (c *Controller) GetMusicFolders(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (c *Controller) StartScan(w http.ResponseWriter, r *http.Request) {
|
||||
scanC := scanner.New(c.DB, c.MusicPath)
|
||||
go scanC.Start()
|
||||
go func() {
|
||||
err := scanner.
|
||||
New(c.DB, c.MusicPath).
|
||||
Start()
|
||||
if err != nil {
|
||||
log.Printf("error while scanning: %v\n", err)
|
||||
}
|
||||
}()
|
||||
c.GetScanStatus(w, r)
|
||||
}
|
||||
|
||||
func (c *Controller) GetScanStatus(w http.ResponseWriter, r *http.Request) {
|
||||
var trackCount int
|
||||
c.DB.Model(&model.Track{}).Count(&trackCount)
|
||||
c.DB.
|
||||
Model(model.Track{}).
|
||||
Count(&trackCount)
|
||||
sub := subsonic.NewResponse()
|
||||
sub.ScanStatus = &subsonic.ScanStatus{
|
||||
Scanning: atomic.LoadInt32(&scanner.IsScanning) == 1,
|
||||
|
||||
@@ -44,7 +44,9 @@ func testNameToPath(name string) string {
|
||||
|
||||
func testQueryCases(t *testing.T, handler http.HandlerFunc, cases []*queryCase) {
|
||||
for _, qc := range cases {
|
||||
qc := qc // pin
|
||||
t.Run(qc.expectPath, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// ensure the handlers give us json
|
||||
qc.params.Add("f", "json")
|
||||
req, _ := http.NewRequest("", "?"+qc.params.Encode(), nil)
|
||||
|
||||
@@ -84,13 +84,13 @@ func makeRequest(method string, params url.Values) (*LastFM, error) {
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
decoder := xml.NewDecoder(resp.Body)
|
||||
var lastfm LastFM
|
||||
err = decoder.Decode(&lastfm)
|
||||
lastfm := &LastFM{}
|
||||
err = decoder.Decode(lastfm)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "decoding")
|
||||
}
|
||||
if lastfm.Error != nil {
|
||||
return nil, fmt.Errorf("parsing: %v", lastfm.Error.Value)
|
||||
}
|
||||
return &lastfm, nil
|
||||
return lastfm, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user