From fc625ac70e09383fab938322968377fedbde954c Mon Sep 17 00:00:00 2001
From: Deluan <github@deluan.com>
Date: Wed, 9 Mar 2016 19:48:43 -0500
Subject: [PATCH] Options to ignore patterns in playlists full path

---
 conf/app.conf             |  3 ++-
 domain/playlist.go        |  7 +++---
 scanner/itunes_scanner.go | 52 +++++++++++++++++++++++++++++++++++----
 3 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/conf/app.conf b/conf/app.conf
index d0bc73b01..08974d432 100644
--- a/conf/app.conf
+++ b/conf/app.conf
@@ -14,7 +14,8 @@ user=deluan
 password=wordpass
 dbPath=./devDb
 downsampleCommand=ffmpeg -i %s -map 0:0 -b:a %bk -v 0 -f mp3 -
-ignorePlsFolders = true
+plsIgnoreFolders = true
+plsIgnoredPatterns = ^iCloud;^CDs para;^Skipped;^Christian
 
 [dev]
 disableValidation = true
diff --git a/domain/playlist.go b/domain/playlist.go
index 7dc3c0215..c2c656cd4 100644
--- a/domain/playlist.go
+++ b/domain/playlist.go
@@ -1,9 +1,10 @@
 package domain
 
 type Playlist struct {
-	Id     string
-	Name   string
-	Tracks []string
+	Id       string
+	Name     string
+	FullPath string
+	Tracks   []string
 }
 
 type PlaylistRepository interface {
diff --git a/scanner/itunes_scanner.go b/scanner/itunes_scanner.go
index 47f8311a0..cf3748288 100644
--- a/scanner/itunes_scanner.go
+++ b/scanner/itunes_scanner.go
@@ -12,6 +12,8 @@ import (
 
 	"html"
 
+	"regexp"
+
 	"github.com/astaxie/beego"
 	"github.com/deluan/gosonic/domain"
 	"github.com/deluan/itl"
@@ -23,9 +25,16 @@ type ItunesScanner struct {
 	albums            map[string]*domain.Album
 	artists           map[string]*domain.Artist
 	playlists         map[string]*domain.Playlist
+	pplaylists        map[string]plsRelation
 	lastModifiedSince time.Time
 }
 
+type plsRelation struct {
+	pID       string
+	parentPID string
+	name      string
+}
+
 func (s *ItunesScanner) ScanLibrary(lastModifiedSince time.Time, path string) (int, error) {
 	beego.Info("Starting iTunes import from:", path)
 	beego.Info("Checking for updates since", lastModifiedSince.String())
@@ -41,6 +50,7 @@ func (s *ItunesScanner) ScanLibrary(lastModifiedSince time.Time, path string) (i
 	s.albums = make(map[string]*domain.Album)
 	s.artists = make(map[string]*domain.Artist)
 	s.playlists = make(map[string]*domain.Playlist)
+	s.pplaylists = make(map[string]plsRelation)
 
 	i := 0
 	for _, t := range l.Tracks {
@@ -55,13 +65,18 @@ func (s *ItunesScanner) ScanLibrary(lastModifiedSince time.Time, path string) (i
 		}
 	}
 
-	ignFolders, _ := beego.AppConfig.Bool("ignorePlsFolders")
+	ignFolders, _ := beego.AppConfig.Bool("plsIgnoreFolders")
+	ignPatterns := beego.AppConfig.Strings("plsIgnoredPatterns")
 	for _, p := range l.Playlists {
-		if p.Master || p.Music || (ignFolders && p.Folder) {
+		rel := plsRelation{pID: p.PlaylistPersistentID, parentPID: p.ParentPersistentID, name: unescape(p.Name)}
+		s.pplaylists[p.PlaylistPersistentID] = rel
+		fullPath := s.fullPath(p.PlaylistPersistentID)
+
+		if s.skipPlaylist(&p, ignFolders, ignPatterns, fullPath) {
 			continue
 		}
 
-		s.collectPlaylists(&p)
+		s.collectPlaylists(&p, fullPath)
 	}
 	beego.Debug("Processed", len(l.Playlists), "playlists.")
 
@@ -81,10 +96,26 @@ func (s *ItunesScanner) Playlists() map[string]*domain.Playlist {
 	return s.playlists
 }
 
-func (s *ItunesScanner) collectPlaylists(p *itl.Playlist) {
+func (s *ItunesScanner) skipPlaylist(p *itl.Playlist, ignFolders bool, ignPatterns []string, fullPath string) bool {
+	if p.Master || p.Music || (ignFolders && p.Folder) {
+		return true
+	}
+
+	for _, p := range ignPatterns {
+		m, _ := regexp.MatchString(p, fullPath)
+		if m {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (s *ItunesScanner) collectPlaylists(p *itl.Playlist, fullPath string) {
 	pl := &domain.Playlist{}
 	pl.Id = strconv.Itoa(p.PlaylistID)
-	pl.Name = p.Name
+	pl.Name = unescape(p.Name)
+	pl.FullPath = fullPath
 	pl.Tracks = make([]string, 0, len(p.PlaylistItems))
 	for _, item := range p.PlaylistItems {
 		id := strconv.Itoa(item.TrackID)
@@ -97,6 +128,17 @@ func (s *ItunesScanner) collectPlaylists(p *itl.Playlist) {
 	}
 }
 
+func (s *ItunesScanner) fullPath(pID string) string {
+	rel, found := s.pplaylists[pID]
+	if !found {
+		return ""
+	}
+	if rel.parentPID == "" {
+		return rel.name
+	}
+	return fmt.Sprintf("%s > %s", s.fullPath(rel.parentPID), rel.name)
+}
+
 func (s *ItunesScanner) collectMediaFiles(t *itl.Track) *domain.MediaFile {
 	mf := &domain.MediaFile{}
 	mf.Id = strconv.Itoa(t.TrackID)