From ee6f81b9e92135fe654e05c383997facaff69bbf Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Fri, 18 Dec 2020 15:44:19 +0000 Subject: [PATCH] Add ability to revert to non-hyphenated user IDs The first 10.7.0 build i tried used hyphens, but a later one didn't. emails.json can now be converted between the two forms depending on what the server uses. --- jfapi/jfapi.go | 10 ++++++++-- main.go | 23 ++++++++++++++++++----- storage.go | 32 ++++++++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/jfapi/jfapi.go b/jfapi/jfapi.go index c75615d..44f1fa8 100644 --- a/jfapi/jfapi.go +++ b/jfapi/jfapi.go @@ -44,6 +44,7 @@ type Jellyfin struct { CacheExpiry time.Time cacheLength int noFail bool + Hyphens bool timeoutHandler common.TimeoutHandler } @@ -208,8 +209,8 @@ func (jf *Jellyfin) post(url string, data map[string]interface{}, response bool) } // DeleteUser deletes the user corresponding to the provided ID. -func (jf *Jellyfin) DeleteUser(id string) (int, error) { - url := fmt.Sprintf("%s/Users/%s", jf.Server, id) +func (jf *Jellyfin) DeleteUser(userID string) (int, error) { + url := fmt.Sprintf("%s/Users/%s", jf.Server, userID) req, _ := http.NewRequest("DELETE", url, nil) for name, value := range jf.header { req.Header.Add(name, value) @@ -239,6 +240,11 @@ func (jf *Jellyfin) GetUsers(public bool) ([]map[string]interface{}, int, error) json.Unmarshal([]byte(data), &result) jf.userCache = result jf.CacheExpiry = time.Now().Add(time.Minute * time.Duration(jf.cacheLength)) + if id, ok := result[0]["Id"]; ok { + if id.(string)[8] == '-' { + jf.Hyphens = true + } + } return result, status, nil } return jf.userCache, 200, nil diff --git a/main.go b/main.go index 7c538ae..3689c47 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,7 @@ type User struct { Password string `json:"password"` } +// contains everything the application needs, essentially. Wouldn't do this in the future. type appContext struct { // defaults *Config config *ini.File @@ -461,7 +462,7 @@ func start(asDaemon, firstCall bool) { app.err.Fatalf("Failed to authenticate with Jellyfin @ %s: Code %d", server, status) } app.info.Printf("Authenticated with %s", server) - // from 10.7.0, jellyfin hyphenates user IDs. This checks if the version is equal or higher. + // from 10.7.0, jellyfin may hyphenate user IDs. This checks if the version is equal or higher. checkVersion := func(version string) int { numberStrings := strings.Split(version, ".") n := 0 @@ -474,6 +475,9 @@ func start(asDaemon, firstCall bool) { return n } if checkVersion(app.jf.ServerInfo.Version) >= checkVersion("10.7.0") { + // Get users to check if server uses hyphenated userIDs + app.jf.GetUsers(false) + noHyphens := true for id := range app.storage.emails { if strings.Contains(id, "-") { @@ -481,10 +485,19 @@ func start(asDaemon, firstCall bool) { break } } - if noHyphens { - app.info.Println(aurora.Yellow("From Jellyfin 10.7.0 onwards, user IDs are hyphenated.\nYour emails.json file will be modified to match this new format.\nA backup will be placed next to the file.\n")) - time.Sleep(time.Second * time.Duration(3)) - newEmails, status, err := app.upgradeEmailStorage(app.storage.emails) + if noHyphens == app.jf.Hyphens { + var newEmails map[string]interface{} + var status int + var err error + if app.jf.Hyphens { + app.info.Println(aurora.Yellow("Your build of Jellyfin appears to hypenate user IDs. Your emails.json file will be modified to match.")) + time.Sleep(time.Second * time.Duration(3)) + newEmails, status, err = app.hyphenateEmailStorage(app.storage.emails) + } else { + app.info.Println(aurora.Yellow("Your emails.json file uses hyphens, but the Jellyfin server no longer does. It will be modified.")) + time.Sleep(time.Second * time.Duration(3)) + newEmails, status, err = app.deHyphenateEmailStorage(app.storage.emails) + } if status != 200 || err != nil { app.err.Printf("Failed to get users from Jellyfin: Code %d", status) app.debug.Printf("Error: %s", err) diff --git a/storage.go b/storage.go index b21e705..e4efd9b 100644 --- a/storage.go +++ b/storage.go @@ -192,10 +192,34 @@ func storeJSON(path string, obj interface{}) error { return err } -// JF 10.7.0 added hyphens to user IDs like this and we need to upgrade email storage to match it: -// [8 chars]-[4]-[4]-[4]-[12] -// This seems consistent, but we'll grab IDs from jellyfin just in case theres some variation. -func (app *appContext) upgradeEmailStorage(old map[string]interface{}) (map[string]interface{}, int, error) { +// One build of JF 10.7.0 hyphenated to user IDs like this and we need to upgrade email storage to match it: +// One build of JF 10.7.0 hyphenated user IDs while another one later didn't. These functions will hyphenate/de-hyphenate email storage. + +func hyphenate(userID string) string { + if userID[8] == '-' { + return userID + } + return userID[:8] + "-" + userID[8:12] + "-" + userID[12:16] + "-" + userID[16:20] + "-" + userID[20:] +} + +func (app *appContext) deHyphenateEmailStorage(old map[string]interface{}) (map[string]interface{}, int, error) { + jfUsers, status, err := app.jf.GetUsers(false) + if status != 200 || err != nil { + return nil, status, err + } + newEmails := map[string]interface{}{} + for _, user := range jfUsers { + unHyphenated := user["Id"].(string) + hyphenated := hyphenate(unHyphenated) + email, ok := old[hyphenated] + if ok { + newEmails[unHyphenated] = email + } + } + return newEmails, status, err +} + +func (app *appContext) hyphenateEmailStorage(old map[string]interface{}) (map[string]interface{}, int, error) { jfUsers, status, err := app.jf.GetUsers(false) if status != 200 || err != nil { return nil, status, err