// // tank // // Import and Playlist Daemon for autoradio project // // // Copyright (C) 2017-2019 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 ( "errors" "fmt" "time" "github.com/jinzhu/gorm" ) const ( FileURIScheme = "file" // well-known table names migrationsTn = "__migrations__" // fixtures publicShowName = "public" ) //******* Errors // TODO: make all errors types??? var ( ErrNotImplemented = errors.New("not implemented") ErrNotFound = gorm.ErrRecordNotFound ErrFileImportNotDone = errors.New("file import is not done") ) type ErrFileInUse struct { Playlists Playlists `json:"playlists"` } func (e *ErrFileInUse) Error() string { return fmt.Sprintf("the file is still in use by %d playlist(s)", len(e.Playlists)) } type ErrInvalidMetadataField string func (e ErrInvalidMetadataField) Error() string { return "invalid metadata field: " + string(e) } //******* Shows type Show struct { Name string `json:"name" gorm:"primary_key"` CreatedAt time.Time `json:"created"` UpdatedAt time.Time `json:"updated"` } func (g Show) String() string { return g.Name } type Shows []Show //******* Files type ImportState int const ( ImportNew ImportState = iota ImportPending ImportRunning ImportDone ImportAborted ) func (s ImportState) String() string { switch s { case ImportNew: return "new" case ImportPending: return "pending" case ImportRunning: return "running" case ImportDone: return "done" case ImportAborted: return "aborted" } return "unknown" } func (s *ImportState) fromString(str string) error { switch str { case "new": *s = ImportNew case "pending": *s = ImportPending case "running": *s = ImportRunning case "done": *s = ImportDone case "aborted": *s = ImportAborted default: return errors.New("invalid import state: '" + str + "'") } return nil } func (s ImportState) MarshalText() (data []byte, err error) { data = []byte(s.String()) return } func (s *ImportState) UnmarshalText(data []byte) (err error) { return s.fromString(string(data)) } // type ImportLogLine struct { // Timestamp time.Time `json:"timestamp"` // Message string `json:"message"` // } // type ImportLog []ImportLogLine // func (l ImportLog) Append(message string) { // l = append(l, ImportLogLine{time.Now(), message}) // } type Import struct { State ImportState `json:"state"` // Log ImportLog `json:"log"` } type FileSource struct { URI string `json:"uri" gorm:"size:1024"` Hash string `json:"hash"` Import Import `json:"import" gorm:"embedded;embedded_prefix:import__"` } type FileMetadata struct { // TODO: actually a full-text index would be nice here... Artist string `json:"artist,omitempty" gorm:"index"` Title string `json:"title,omitempty" gorm:"index"` Album string `json:"album,omitempty" gorm:"index"` // TODO: add more fields } type File struct { ID uint64 `json:"id" gorm:"primary_key"` CreatedAt time.Time `json:"created"` UpdatedAt time.Time `json:"updated"` ShowName string `json:"show" gorm:"not null;index"` Show Show `json:"-" gorm:"association_foreignkey:Name"` Source FileSource `json:"source" gorm:"embedded;embedded_prefix:source__"` Metadata FileMetadata `json:"metadata" gorm:"embedded;embedded_prefix:metadata__"` Size uint64 `json:"size"` Duration time.Duration `json:"duration"` } type Files []File //******* Playlists type PlaylistEntry struct { ID uint64 `json:"-" gorm:"primary_key"` PlaylistID uint64 `json:"-" gorm:"not null;index;unique_index:unique_playlist_line_numbers"` LineNum uint `json:"-" gorm:"not null;unique_index:unique_playlist_line_numbers"` URI string `json:"uri" gorm:"size:1024"` File *File `json:"file,omitempty" gorm:"association_autoupdate:false;association_autocreate:false"` FileID *uint64 `json:"-" gorm:"index"` } type Playlist struct { ID uint64 `json:"id" gorm:"primary_key"` CreatedAt time.Time `json:"created"` UpdatedAt time.Time `json:"updated"` Description string `json:"description"` ShowName string `json:"show" gorm:"not null;index"` Show Show `json:"-" gorm:"association_foreignkey:Name"` Entries []PlaylistEntry `json:"entries,omitempty"` } type Playlists []Playlist //****************