Newer
Older
//
// tank
//
// Import and Playlist Daemon for autoradio project
//
//
// Copyright (C) 2017-2018 Christian Pointner <equinox@helsinki.at>
//
// This file is part of tank.
//
// tank is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// tank is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with tank. If not, see <http://www.gnu.org/licenses/>.
//
package store
import (
"fmt"
"net/url"
"strconv"
"github.com/jinzhu/gorm"
)
func (p *Playlist) BeforeSave() error {
for idx := range p.Entries {
p.Entries[idx].LineNum = uint(idx)
if p.Entries[idx].File != nil {
p.Entries[idx].URI = "" // this will be regenerated in AfterFind()
} else if p.Entries[idx].URI != "" {
uri, err := url.Parse(p.Entries[idx].URI)
if err != nil {
return fmt.Errorf("playlist entry #%d is invalid: %v", idx, err)
}
if uri.Scheme == FileURIScheme {
if uri.Host == "" || uri.Path == "" {
return fmt.Errorf("playlist entry #%d is invalid: uri must be in the format %s://<group>/<file-id>", idx, FileURIScheme)
}
fileID, err := strconv.ParseUint(strings.TrimPrefix(uri.Path, "/"), 10, 64)
if err != nil {
return fmt.Errorf("playlist entry #%d is invalid: %v", idx, err)
}
p.Entries[idx].File = &File{ID: fileID, GroupName: uri.Host}
p.Entries[idx].URI = "" // this will be regenerated in AfterFind()
}
} else {
return fmt.Errorf("playlist entry #%d is invalid, entries must either contain a File or have a URI set", idx)
}
return nil
}
func (p *Playlist) AfterFind() error {
for idx := range p.Entries {
if p.Entries[idx].File != nil {
urihost := p.Entries[idx].File.GroupName
uripath := strconv.FormatUint(p.Entries[idx].File.ID, 10)
uri := url.URL{Scheme: FileURIScheme, Host: urihost, Path: uripath}
p.Entries[idx].URI = uri.String()
}
}
return nil
func (st *Store) ListPlaylists(group string) (playlists Playlists, err error) {
err = st.db.Where("group_name = ?", group).Preload("Entries", func(db *gorm.DB) *gorm.DB {
return db.Order("playlist_entries.line_num asc")
}).Preload("Entries.File").Find(&playlists).Error
func (st *Store) CreatePlaylist(group string, playlist Playlist) (*Playlist, error) {
if _, err := st.CreateGroup(group); err != nil {
return nil, err
}
playlist.ID = 0
playlist.GroupName = group
err := st.db.Create(&playlist).Error
// TODO: the returned playlist object will not contain properly initialized File Objects
return &playlist, err
}
func (st *Store) GetPlaylist(group string, id uint64) (playlist *Playlist, err error) {
playlist = &Playlist{}
// we have to make sure that the playlist actually belongs to <group>
// otherwise a bad user can trick us into returning playlists for groups it
// normally has no access to
err = st.db.Where("group_name = ?", group).Preload("Entries", func(db *gorm.DB) *gorm.DB {
return db.Order("playlist_entries.line_num ASC")
}).Preload("Entries.File").First(playlist, id).Error
func (st *Store) UpdatePlaylist(group string, id uint64, playlist Playlist) (*Playlist, error) {
return nil, ErrNotImplented
func (st *Store) DeletePlaylist(group string, id uint64) (err error) {
tx := st.db.Begin()
// make sure the playlist exists and actually belongs to <group>
if err = tx.Where("group_name = ?", group).First(&Playlist{}, id).Error; err != nil {
tx.Rollback()
return
}
if err = tx.Delete(&Playlist{ID: id}).Error; err != nil {
tx.Rollback()
return
}
tx.Commit()
return