package movies import ( "encoding/json" "fmt" "io/ioutil" "os" "sync" ) type Collection struct { Movies []*Movie movieMap map[string]*Movie Lists []*List listMap map[string]*List Files *FileSource mutex sync.RWMutex hasChanged bool } func Import(filename string) (*Collection, error) { b, err := ioutil.ReadFile(filename) if err != nil { return nil, err } var c Collection if err := json.Unmarshal(b, &c); err != nil { return nil, err } c.movieMap = make(map[string]*Movie) for _, m := range c.Movies { m.FillFromOMDB() c.movieMap[m.IMDBID] = m } c.listMap = make(map[string]*List) for _, l := range c.Lists { c.listMap[l.ID] = l } return &c, nil } func (c *Collection) Export(filename string) error { c.mutex.RLock() defer c.mutex.RUnlock() b, err := json.Marshal(c) if err != nil { return err } err = ioutil.WriteFile(filename, b, 0644) if err != nil { return err } c.hasChanged = false return nil } func (c *Collection) Add(m *Movie) { c.mutex.Lock() defer c.mutex.Unlock() c.hasChanged = true for _, present := range c.Movies { if m.IMDBID == present.IMDBID { present.OMDB = m.OMDB present.FillFromOMDB() return } } c.Movies = append(c.Movies, m) c.movieMap[m.IMDBID] = m } func (c *Collection) HasChanged() bool { return c.hasChanged } func (c *Collection) Get(imdbID string) (*Movie, bool) { c.mutex.RLock() defer c.mutex.RUnlock() m, ok := c.movieMap[imdbID] return m, ok } func (c *Collection) Update(m *Movie) { c.mutex.Lock() defer c.mutex.Unlock() c.movieMap[m.IMDBID] = m found := false for i := range c.Movies { if c.Movies[i].IMDBID == m.IMDBID { c.Movies[i] = m found = true break } } if !found { c.Movies = append(c.Movies, m) } c.hasChanged = true } func (c *Collection) GetList(listID string) (*List, bool) { c.mutex.RLock() defer c.mutex.RUnlock() l, ok := c.listMap[listID] return l, ok } func (c *Collection) AddList(id, title string) error { c.mutex.Lock() defer c.mutex.Unlock() c.hasChanged = true for _, present := range c.Lists { if id == present.ID { return fmt.Errorf("there is already a list with id %q", id) } } l := &List{ ID: id, Title: title, } c.Lists = append(c.Lists, l) c.listMap[l.ID] = l return nil } func (c *Collection) UpdateList(l *List) { c.mutex.Lock() defer c.mutex.Unlock() c.listMap[l.ID] = l found := false for i := range c.Lists { if c.Lists[i].ID == l.ID { c.Lists[i] = l found = true break } } if !found { c.Lists = append(c.Lists, l) } c.hasChanged = true } func (c *Collection) AllFiles() []string { if c.Files == nil { return nil } return c.Files.Files } func (c *Collection) SearchFiles(query string) []string { return c.Files.Search(query) } func (c *Collection) ScanFiles(root string) error { c.mutex.Lock() defer c.mutex.Unlock() if c.Files == nil { c.Files = &FileSource{} } if err := c.Files.Scan(os.Getenv("FILE_ROOT")); err != nil { return err } c.hasChanged = true return nil }