-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
133 lines (111 loc) · 3.01 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"context"
"errors"
"flag"
"fmt"
"log"
"plex-maid/pkg/metadata"
"plex-maid/pkg/plex"
)
var (
pc *plex.Client
scrobbler metadata.Scrobbler
)
func main() {
flagPlexURL := flag.String("url", "", "URL of plex")
flagToLock := flag.Bool("toLock", false, "Lock the change in Plex")
flag.Parse()
var (
err error
)
pc, err = plex.NewClient(*flagPlexURL)
if err != nil {
log.Fatalf("Failed to start Plex client: %s", err)
}
scrobbler, err = metadata.NewMusicbrainz()
if err != nil {
log.Fatalf("Failed to start scrobbler: %s", err)
}
resp, err := pc.GetAllLibrary()
if err != nil {
log.Fatalf("Failed to fetch all library: %s", err)
}
log.Printf("Found library: %+v", resp.MediaContainer.Directory)
for _, lib := range resp.MediaContainer.Directory {
if !lib.Refreshing {
scanAndUpdateLibrary(lib.Key, *flagToLock)
}
}
}
func scanAndUpdateLibrary(libraryID string, lock bool) {
sectionsC := make(chan *plex.SectionsGetResponse)
ctx := context.Background()
err := pc.GetAllSections(ctx, libraryID, plex.ByArtist, sectionsC)
if err != nil {
log.Fatal(err)
}
for containers := range sectionsC {
for _, obj := range containers.MediaContainer.Metadata {
name := obj.Title
log.Printf("Found artist %s on plex: %+v", name, obj)
if skip, err := toSkipArtist(obj.RatingKey); err != nil {
log.Printf("Failed to determine if artist is locked: %s", err)
} else if skip {
log.Printf("skipping %s", name)
continue
}
artist, err := scrobbler.SearchArtist(ctx, name)
if err != nil {
log.Printf("Error while trying to search artist [%s]: %s", name, err)
continue
}
artist.ToSimplified()
log.Printf("Musicbrainz found match for %s: %+v", name, artist)
boolToInt := func(b bool) int {
if b {
return 1
}
return 0
}
// update artist with new metadata
// enhance searching experience by adding aliases in title sort
titleSort := fmt.Sprintf("%s | %s", artist.SortName, artist.Aliases)
params := plex.SectionsPutRequest{
Type: plex.ByArtist,
ID: obj.RatingKey,
Title: artist.Name,
TitleSort: titleSort,
TitleLocked: boolToInt(lock),
TitleSortLocked: boolToInt(lock),
}
if err := pc.PutSections(libraryID, params); err != nil {
log.Printf("Failed to update artist %s: %s", name, err)
}
}
}
}
// determine if an artist should be skipped
func toSkipArtist(id string) (bool, error) {
// check if lock
artistContainer, err := pc.GetMetadata(id)
if err != nil {
log.Printf("Failed to fetch metadata of %s: %s", id, err)
return false, err
}
if len(artistContainer.MediaContainer.Metadata) == 0 {
return false, errors.New("Unexpected metadata length 0")
}
artistObj := artistContainer.MediaContainer.Metadata[0]
for _, field := range artistObj.Field {
// title is locked
if field.Name == "title" && field.Locked {
return true, nil
}
}
// incomplete metedata
if artistObj.UpdatedAt == 0 {
return true, nil
}
return false, nil
}