diff --git a/cmd/main.go b/cmd/main.go index bf25d95..483e209 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -37,6 +37,8 @@ func main() { log.Fatal(err) } + libraryType := locator.GetLibraryType(cfg, sectionID) + ids, titles := locator.GetTitles(cfg, sectionID, days) if check { @@ -47,11 +49,18 @@ func main() { } if delete { - files := eraser.LookupFileLocation(cfg, ids) - err = eraser.DeleteMedia(delete, files) - if err != nil { - log.Println(err) + if libraryType == "movie" { + files := eraser.LookupMovieFileLocation(cfg, ids) + err = eraser.DeleteFiles(delete, files) + if err != nil { + log.Println(err) + } + } else if libraryType == "show" { + files := eraser.LookupTVFileLocation(cfg, ids) + err = eraser.DeleteFiles(delete, files) + if err != nil { + log.Println(err) + } } } - } diff --git a/pkg/eraser/eraser.go b/pkg/eraser/eraser.go index c9a8f15..197e24c 100644 --- a/pkg/eraser/eraser.go +++ b/pkg/eraser/eraser.go @@ -13,17 +13,14 @@ import ( "git.linuxrocker.com/mattburchett/Housekeeper/pkg/model" ) -// LookupFileLocation will gather a list of Information based on IDs returned by locator.GetTitles -func LookupFileLocation(config config.Config, ids []int) []string { +// LookupMovieFileLocation will gather a list of Information based on IDs returned by locator.GetTitles +func LookupMovieFileLocation(config config.Config, ids []int) []string { fileList := make([]string, 0) for _, i := range ids { plexURL := fmt.Sprintf("%s:%d%s%d%s%s", config.PlexHost, config.PlexPort, "/library/metadata/", i, "/?X-Plex-Token=", config.PlexToken) req, err := http.NewRequest(http.MethodGet, plexURL, nil) - if err != nil { - log.Fatal(err) - } httpClient := http.Client{} req.Header.Set("User-Agent", "Housekeeper") @@ -41,15 +38,62 @@ func LookupFileLocation(config config.Config, ids []int) []string { if err != nil { log.Fatal(err) } - plexModel := model.XMLPlexAPI{} + plexModel := model.XMLPlexMovieAPI{} xml.Unmarshal(body, &plexModel) fileList = append(fileList, filepath.Dir(plexModel.Video.Media.Part.File)) } return fileList } -// DeleteMedia will actually perform the deletion. -func DeleteMedia(delete bool, files []string) error { +// LookupTVFileLocation will gather a list of Information based on IDs returned by locator.GetTitles +func LookupTVFileLocation(config config.Config, ids []int) []string { + fileList := make([]string, 0) + m := make(map[string]bool) + results := make([]string, 0) + + for _, i := range ids { + plexURL := fmt.Sprintf("%s:%d%s%d%s%s", config.PlexHost, config.PlexPort, "/library/metadata/", i, "/allLeaves/?X-Plex-Token=", config.PlexToken) + + req, err := http.NewRequest(http.MethodGet, plexURL, nil) + + httpClient := http.Client{} + req.Header.Set("User-Agent", "Housekeeper") + + res, getErr := httpClient.Do(req) + if getErr != nil { + log.Fatal(getErr) + } + + body, readErr := ioutil.ReadAll(res.Body) + if readErr != nil { + log.Fatal(readErr) + } + + if err != nil { + log.Fatal(err) + } + plexModel := model.XMLPlexTVAPI{} + xml.Unmarshal(body, &plexModel) + + plexTV := plexModel.Video + + for _, i := range plexTV { + fileList = append(fileList, filepath.Dir(filepath.Dir(i.Media.Part.File))) + } + + for _, r := range fileList { + if _, ok := m[r]; !ok { + m[r] = true + results = append(results, r) + } + } + + } + return results +} + +// DeleteFiles will actually perform the deletion. +func DeleteFiles(delete bool, files []string) error { var err error if delete { for _, i := range files { diff --git a/pkg/locator/locator.go b/pkg/locator/locator.go index ec17c05..be3f1f3 100644 --- a/pkg/locator/locator.go +++ b/pkg/locator/locator.go @@ -2,6 +2,7 @@ package locator import ( "encoding/json" + "encoding/xml" "fmt" "io/ioutil" "log" @@ -14,6 +15,44 @@ import ( "git.linuxrocker.com/mattburchett/Housekeeper/pkg/util" ) +// GetLibraryType checks to see what type the library is. +func GetLibraryType(config config.Config, sectionID int) string { + typeURL := fmt.Sprintf("%s:%d%s%d%s%s", config.PlexHost, config.PlexPort, "/library/sections/", sectionID, "/?X-Plex-Token=", config.PlexToken) + + req, err := http.NewRequest(http.MethodGet, typeURL, nil) + httpClient := http.Client{} + req.Header.Set("User-Agent", "Housekeeper") + + res, getErr := httpClient.Do(req) + if getErr != nil { + log.Fatal(getErr) + } + + body, readErr := ioutil.ReadAll(res.Body) + if readErr != nil { + log.Fatal(readErr) + } + + if err != nil { + log.Fatal(err) + } + + typeModel := model.XMLPlexLibraryType{} + xml.Unmarshal(body, &typeModel) + + var libraryType string + + if typeModel.Thumb == "/:/resources/movie.png" { + libraryType = "movie" + } else if typeModel.Thumb == "/:/resources/show.png" { + libraryType = "show" + } else { + log.Fatal("Unsupported library type found. This app only supports movies and shows.") + } + + return libraryType +} + // GetCount will gather a count of media in a specific library, required for GetTitles. func GetCount(config config.Config, sectionID int) int { countURL := fmt.Sprintf("%s%s%s%s%s%d", config.BaseURL, config.PlexPyContext, "/api/v2?apikey=", config.PlexPyAPIKey, "&cmd=get_library§ion_id=", sectionID) diff --git a/pkg/model/eraser_model.go b/pkg/model/eraser_model.go new file mode 100644 index 0000000..a79a5f1 --- /dev/null +++ b/pkg/model/eraser_model.go @@ -0,0 +1,232 @@ +package model + +import "encoding/xml" + +// XMLPlexMovieAPI - This is the XML version of the Library. +type XMLPlexMovieAPI struct { + XMLName xml.Name `xml:"MediaContainer"` + Text string `xml:",chardata"` + Size string `xml:"size,attr"` + AllowSync string `xml:"allowSync,attr"` + Identifier string `xml:"identifier,attr"` + LibrarySectionID string `xml:"librarySectionID,attr"` + LibrarySectionTitle string `xml:"librarySectionTitle,attr"` + LibrarySectionUUID string `xml:"librarySectionUUID,attr"` + MediaTagPrefix string `xml:"mediaTagPrefix,attr"` + MediaTagVersion string `xml:"mediaTagVersion,attr"` + Video struct { + Text string `xml:",chardata"` + RatingKey string `xml:"ratingKey,attr"` + Key string `xml:"key,attr"` + GUID string `xml:"guid,attr"` + LibrarySectionTitle string `xml:"librarySectionTitle,attr"` + LibrarySectionID string `xml:"librarySectionID,attr"` + LibrarySectionKey string `xml:"librarySectionKey,attr"` + Studio string `xml:"studio,attr"` + Type string `xml:"type,attr"` + Title string `xml:"title,attr"` + ContentRating string `xml:"contentRating,attr"` + Summary string `xml:"summary,attr"` + Rating string `xml:"rating,attr"` + AudienceRating string `xml:"audienceRating,attr"` + Year string `xml:"year,attr"` + Tagline string `xml:"tagline,attr"` + Thumb string `xml:"thumb,attr"` + Art string `xml:"art,attr"` + Duration string `xml:"duration,attr"` + OriginallyAvailableAt string `xml:"originallyAvailableAt,attr"` + AddedAt string `xml:"addedAt,attr"` + UpdatedAt string `xml:"updatedAt,attr"` + AudienceRatingImage string `xml:"audienceRatingImage,attr"` + ChapterSource string `xml:"chapterSource,attr"` + PrimaryExtraKey string `xml:"primaryExtraKey,attr"` + RatingImage string `xml:"ratingImage,attr"` + Media struct { + Text string `xml:",chardata"` + VideoResolution string `xml:"videoResolution,attr"` + ID string `xml:"id,attr"` + Duration string `xml:"duration,attr"` + Bitrate string `xml:"bitrate,attr"` + Width string `xml:"width,attr"` + Height string `xml:"height,attr"` + AspectRatio string `xml:"aspectRatio,attr"` + AudioChannels string `xml:"audioChannels,attr"` + AudioCodec string `xml:"audioCodec,attr"` + VideoCodec string `xml:"videoCodec,attr"` + Container string `xml:"container,attr"` + VideoFrameRate string `xml:"videoFrameRate,attr"` + AudioProfile string `xml:"audioProfile,attr"` + VideoProfile string `xml:"videoProfile,attr"` + Part struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Key string `xml:"key,attr"` + Duration string `xml:"duration,attr"` + File string `xml:"file,attr"` + Size string `xml:"size,attr"` + AudioProfile string `xml:"audioProfile,attr"` + Container string `xml:"container,attr"` + VideoProfile string `xml:"videoProfile,attr"` + Stream []struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + StreamType string `xml:"streamType,attr"` + Default string `xml:"default,attr"` + Codec string `xml:"codec,attr"` + Index string `xml:"index,attr"` + Bitrate string `xml:"bitrate,attr"` + Language string `xml:"language,attr"` + LanguageCode string `xml:"languageCode,attr"` + BitDepth string `xml:"bitDepth,attr"` + ChromaLocation string `xml:"chromaLocation,attr"` + ChromaSubsampling string `xml:"chromaSubsampling,attr"` + FrameRate string `xml:"frameRate,attr"` + HasScalingMatrix string `xml:"hasScalingMatrix,attr"` + Height string `xml:"height,attr"` + Level string `xml:"level,attr"` + Profile string `xml:"profile,attr"` + RefFrames string `xml:"refFrames,attr"` + ScanType string `xml:"scanType,attr"` + Title string `xml:"title,attr"` + Width string `xml:"width,attr"` + DisplayTitle string `xml:"displayTitle,attr"` + Selected string `xml:"selected,attr"` + Channels string `xml:"channels,attr"` + AudioChannelLayout string `xml:"audioChannelLayout,attr"` + SamplingRate string `xml:"samplingRate,attr"` + Key string `xml:"key,attr"` + } `xml:"Stream"` + } `xml:"Part"` + } `xml:"Media"` + Genre []struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Filter string `xml:"filter,attr"` + Tag string `xml:"tag,attr"` + } `xml:"Genre"` + Director struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Filter string `xml:"filter,attr"` + Tag string `xml:"tag,attr"` + } `xml:"Director"` + Writer []struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Filter string `xml:"filter,attr"` + Tag string `xml:"tag,attr"` + } `xml:"Writer"` + Producer []struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Filter string `xml:"filter,attr"` + Tag string `xml:"tag,attr"` + } `xml:"Producer"` + Country struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Filter string `xml:"filter,attr"` + Tag string `xml:"tag,attr"` + } `xml:"Country"` + Role []struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Filter string `xml:"filter,attr"` + Tag string `xml:"tag,attr"` + Role string `xml:"role,attr"` + Thumb string `xml:"thumb,attr"` + } `xml:"Role"` + } `xml:"Video"` +} + +// XMLPlexTVAPI - This is the XML version of the Library. +type XMLPlexTVAPI struct { + XMLName xml.Name `xml:"MediaContainer"` + Text string `xml:",chardata"` + Size string `xml:"size,attr"` + AllowSync string `xml:"allowSync,attr"` + Art string `xml:"art,attr"` + Banner string `xml:"banner,attr"` + Identifier string `xml:"identifier,attr"` + Key string `xml:"key,attr"` + LibrarySectionID string `xml:"librarySectionID,attr"` + LibrarySectionTitle string `xml:"librarySectionTitle,attr"` + LibrarySectionUUID string `xml:"librarySectionUUID,attr"` + MediaTagPrefix string `xml:"mediaTagPrefix,attr"` + MediaTagVersion string `xml:"mediaTagVersion,attr"` + MixedParents string `xml:"mixedParents,attr"` + Nocache string `xml:"nocache,attr"` + ParentIndex string `xml:"parentIndex,attr"` + ParentTitle string `xml:"parentTitle,attr"` + ParentYear string `xml:"parentYear,attr"` + Theme string `xml:"theme,attr"` + Title1 string `xml:"title1,attr"` + Title2 string `xml:"title2,attr"` + ViewGroup string `xml:"viewGroup,attr"` + ViewMode string `xml:"viewMode,attr"` + Video []struct { + Text string `xml:",chardata"` + RatingKey string `xml:"ratingKey,attr"` + Key string `xml:"key,attr"` + ParentRatingKey string `xml:"parentRatingKey,attr"` + GrandparentRatingKey string `xml:"grandparentRatingKey,attr"` + Studio string `xml:"studio,attr"` + Type string `xml:"type,attr"` + Title string `xml:"title,attr"` + GrandparentKey string `xml:"grandparentKey,attr"` + ParentKey string `xml:"parentKey,attr"` + GrandparentTitle string `xml:"grandparentTitle,attr"` + ParentTitle string `xml:"parentTitle,attr"` + ContentRating string `xml:"contentRating,attr"` + Summary string `xml:"summary,attr"` + Index string `xml:"index,attr"` + ParentIndex string `xml:"parentIndex,attr"` + Rating string `xml:"rating,attr"` + Year string `xml:"year,attr"` + Thumb string `xml:"thumb,attr"` + Art string `xml:"art,attr"` + ParentThumb string `xml:"parentThumb,attr"` + GrandparentThumb string `xml:"grandparentThumb,attr"` + GrandparentArt string `xml:"grandparentArt,attr"` + GrandparentTheme string `xml:"grandparentTheme,attr"` + Duration string `xml:"duration,attr"` + OriginallyAvailableAt string `xml:"originallyAvailableAt,attr"` + AddedAt string `xml:"addedAt,attr"` + UpdatedAt string `xml:"updatedAt,attr"` + TitleSort string `xml:"titleSort,attr"` + Media struct { + Text string `xml:",chardata"` + VideoResolution string `xml:"videoResolution,attr"` + ID string `xml:"id,attr"` + Duration string `xml:"duration,attr"` + Bitrate string `xml:"bitrate,attr"` + Width string `xml:"width,attr"` + Height string `xml:"height,attr"` + AspectRatio string `xml:"aspectRatio,attr"` + AudioChannels string `xml:"audioChannels,attr"` + AudioCodec string `xml:"audioCodec,attr"` + VideoCodec string `xml:"videoCodec,attr"` + Container string `xml:"container,attr"` + VideoFrameRate string `xml:"videoFrameRate,attr"` + VideoProfile string `xml:"videoProfile,attr"` + Part struct { + Text string `xml:",chardata"` + ID string `xml:"id,attr"` + Key string `xml:"key,attr"` + Duration string `xml:"duration,attr"` + File string `xml:"file,attr"` + Size string `xml:"size,attr"` + Container string `xml:"container,attr"` + VideoProfile string `xml:"videoProfile,attr"` + } `xml:"Part"` + } `xml:"Media"` + Director struct { + Text string `xml:",chardata"` + Tag string `xml:"tag,attr"` + } `xml:"Director"` + Writer []struct { + Text string `xml:",chardata"` + Tag string `xml:"tag,attr"` + } `xml:"Writer"` + } `xml:"Video"` +} diff --git a/pkg/model/locator_model.go b/pkg/model/locator_model.go index b8a0e44..b3308e7 100644 --- a/pkg/model/locator_model.go +++ b/pkg/model/locator_model.go @@ -63,139 +63,28 @@ type PlexPyMediaInfo struct { } `json:"response"` } -// XMLPlexAPI - This is the XML version of the struct below it. -type XMLPlexAPI struct { - XMLName xml.Name `xml:"MediaContainer"` - Text string `xml:",chardata"` - Size string `xml:"size,attr"` - AllowSync string `xml:"allowSync,attr"` - Identifier string `xml:"identifier,attr"` - LibrarySectionID string `xml:"librarySectionID,attr"` - LibrarySectionTitle string `xml:"librarySectionTitle,attr"` - LibrarySectionUUID string `xml:"librarySectionUUID,attr"` - MediaTagPrefix string `xml:"mediaTagPrefix,attr"` - MediaTagVersion string `xml:"mediaTagVersion,attr"` - Video struct { - Text string `xml:",chardata"` - RatingKey string `xml:"ratingKey,attr"` - Key string `xml:"key,attr"` - GUID string `xml:"guid,attr"` - LibrarySectionTitle string `xml:"librarySectionTitle,attr"` - LibrarySectionID string `xml:"librarySectionID,attr"` - LibrarySectionKey string `xml:"librarySectionKey,attr"` - Studio string `xml:"studio,attr"` - Type string `xml:"type,attr"` - Title string `xml:"title,attr"` - ContentRating string `xml:"contentRating,attr"` - Summary string `xml:"summary,attr"` - Rating string `xml:"rating,attr"` - AudienceRating string `xml:"audienceRating,attr"` - Year string `xml:"year,attr"` - Tagline string `xml:"tagline,attr"` - Thumb string `xml:"thumb,attr"` - Art string `xml:"art,attr"` - Duration string `xml:"duration,attr"` - OriginallyAvailableAt string `xml:"originallyAvailableAt,attr"` - AddedAt string `xml:"addedAt,attr"` - UpdatedAt string `xml:"updatedAt,attr"` - AudienceRatingImage string `xml:"audienceRatingImage,attr"` - ChapterSource string `xml:"chapterSource,attr"` - PrimaryExtraKey string `xml:"primaryExtraKey,attr"` - RatingImage string `xml:"ratingImage,attr"` - Media struct { - Text string `xml:",chardata"` - VideoResolution string `xml:"videoResolution,attr"` - ID string `xml:"id,attr"` - Duration string `xml:"duration,attr"` - Bitrate string `xml:"bitrate,attr"` - Width string `xml:"width,attr"` - Height string `xml:"height,attr"` - AspectRatio string `xml:"aspectRatio,attr"` - AudioChannels string `xml:"audioChannels,attr"` - AudioCodec string `xml:"audioCodec,attr"` - VideoCodec string `xml:"videoCodec,attr"` - Container string `xml:"container,attr"` - VideoFrameRate string `xml:"videoFrameRate,attr"` - AudioProfile string `xml:"audioProfile,attr"` - VideoProfile string `xml:"videoProfile,attr"` - Part struct { - Text string `xml:",chardata"` - ID string `xml:"id,attr"` - Key string `xml:"key,attr"` - Duration string `xml:"duration,attr"` - File string `xml:"file,attr"` - Size string `xml:"size,attr"` - AudioProfile string `xml:"audioProfile,attr"` - Container string `xml:"container,attr"` - VideoProfile string `xml:"videoProfile,attr"` - Stream []struct { - Text string `xml:",chardata"` - ID string `xml:"id,attr"` - StreamType string `xml:"streamType,attr"` - Default string `xml:"default,attr"` - Codec string `xml:"codec,attr"` - Index string `xml:"index,attr"` - Bitrate string `xml:"bitrate,attr"` - Language string `xml:"language,attr"` - LanguageCode string `xml:"languageCode,attr"` - BitDepth string `xml:"bitDepth,attr"` - ChromaLocation string `xml:"chromaLocation,attr"` - ChromaSubsampling string `xml:"chromaSubsampling,attr"` - FrameRate string `xml:"frameRate,attr"` - HasScalingMatrix string `xml:"hasScalingMatrix,attr"` - Height string `xml:"height,attr"` - Level string `xml:"level,attr"` - Profile string `xml:"profile,attr"` - RefFrames string `xml:"refFrames,attr"` - ScanType string `xml:"scanType,attr"` - Title string `xml:"title,attr"` - Width string `xml:"width,attr"` - DisplayTitle string `xml:"displayTitle,attr"` - Selected string `xml:"selected,attr"` - Channels string `xml:"channels,attr"` - AudioChannelLayout string `xml:"audioChannelLayout,attr"` - SamplingRate string `xml:"samplingRate,attr"` - Key string `xml:"key,attr"` - } `xml:"Stream"` - } `xml:"Part"` - } `xml:"Media"` - Genre []struct { - Text string `xml:",chardata"` - ID string `xml:"id,attr"` - Filter string `xml:"filter,attr"` - Tag string `xml:"tag,attr"` - } `xml:"Genre"` - Director struct { - Text string `xml:",chardata"` - ID string `xml:"id,attr"` - Filter string `xml:"filter,attr"` - Tag string `xml:"tag,attr"` - } `xml:"Director"` - Writer []struct { - Text string `xml:",chardata"` - ID string `xml:"id,attr"` - Filter string `xml:"filter,attr"` - Tag string `xml:"tag,attr"` - } `xml:"Writer"` - Producer []struct { - Text string `xml:",chardata"` - ID string `xml:"id,attr"` - Filter string `xml:"filter,attr"` - Tag string `xml:"tag,attr"` - } `xml:"Producer"` - Country struct { - Text string `xml:",chardata"` - ID string `xml:"id,attr"` - Filter string `xml:"filter,attr"` - Tag string `xml:"tag,attr"` - } `xml:"Country"` - Role []struct { - Text string `xml:",chardata"` - ID string `xml:"id,attr"` - Filter string `xml:"filter,attr"` - Tag string `xml:"tag,attr"` - Role string `xml:"role,attr"` - Thumb string `xml:"thumb,attr"` - } `xml:"Role"` - } `xml:"Video"` +type XMLPlexLibraryType struct { + XMLName xml.Name `xml:"MediaContainer"` + Text string `xml:",chardata"` + Size string `xml:"size,attr"` + AllowSync string `xml:"allowSync,attr"` + Art string `xml:"art,attr"` + Content string `xml:"content,attr"` + Identifier string `xml:"identifier,attr"` + LibrarySectionID string `xml:"librarySectionID,attr"` + MediaTagPrefix string `xml:"mediaTagPrefix,attr"` + MediaTagVersion string `xml:"mediaTagVersion,attr"` + Nocache string `xml:"nocache,attr"` + Thumb string `xml:"thumb,attr"` + Title1 string `xml:"title1,attr"` + ViewGroup string `xml:"viewGroup,attr"` + ViewMode string `xml:"viewMode,attr"` + Directory []struct { + Text string `xml:",chardata"` + Key string `xml:"key,attr"` + Title string `xml:"title,attr"` + Secondary string `xml:"secondary,attr"` + Prompt string `xml:"prompt,attr"` + Search string `xml:"search,attr"` + } `xml:"Directory"` }