From 3c952d21f7586ebe26d0db838cc8a8fd618642d9 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Sun, 29 Nov 2020 18:01:10 +0000 Subject: [PATCH] fix 10.7.0 compatibility, simplify scss Hyphens are added to user IDs from 10.7.0, so if the server is running it, emails.json will be modified to include them. The existing file is backed up. Also, scss files have been simplified since bs4-jf and bs5-jf share much of the same content. --- jfapi/jfapi.go | 2 +- main.go | 42 ++++++++++++ scss/bs4/bs4-jf.scss | 145 +----------------------------------------- scss/bs5/bs5-jf.scss | 148 +------------------------------------------ scss/jf-post.scss | 41 ++++++++++++ scss/jf-pre.scss | 101 +++++++++++++++++++++++++++++ storage.go | 21 ++++++ 7 files changed, 211 insertions(+), 289 deletions(-) create mode 100644 scss/jf-post.scss create mode 100644 scss/jf-pre.scss diff --git a/jfapi/jfapi.go b/jfapi/jfapi.go index 27c5586..c75615d 100644 --- a/jfapi/jfapi.go +++ b/jfapi/jfapi.go @@ -57,7 +57,7 @@ func NewJellyfin(server, client, version, device, deviceID string, timeoutHandle jf.deviceID = deviceID jf.useragent = fmt.Sprintf("%s/%s", client, version) jf.timeoutHandler = timeoutHandler - jf.auth = fmt.Sprintf("MediaBrowser Client=%s, Device=%s, DeviceId=%s, Version=%s", client, device, deviceID, version) + jf.auth = fmt.Sprintf("MediaBrowser Client=\"%s\", Device=\"%s\", DeviceId=\"%s\", Version=\"%s\"", client, device, deviceID, version) jf.header = map[string]string{ "Accept": "application/json", "Content-type": "application/json; charset=UTF-8", diff --git a/main.go b/main.go index 78da16a..7c538ae 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( "os/signal" "path/filepath" "runtime" + "strconv" "strings" "time" @@ -460,6 +461,47 @@ 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. + checkVersion := func(version string) int { + numberStrings := strings.Split(version, ".") + n := 0 + for _, s := range numberStrings { + num, err := strconv.Atoi(s) + if err == nil { + n += num + } + } + return n + } + if checkVersion(app.jf.ServerInfo.Version) >= checkVersion("10.7.0") { + noHyphens := true + for id := range app.storage.emails { + if strings.Contains(id, "-") { + noHyphens = false + 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 status != 200 || err != nil { + app.err.Printf("Failed to get users from Jellyfin: Code %d", status) + app.debug.Printf("Error: %s", err) + app.err.Fatalf("Couldn't upgrade emails.json") + } + bakFile := app.storage.emails_path + ".bak" + err = storeJSON(bakFile, app.storage.emails) + if err != nil { + app.err.Fatalf("couldn't store emails.json backup: %s", err) + } + app.storage.emails = newEmails + err = app.storage.storeEmails() + if err != nil { + app.err.Fatalf("couldn't store emails.json: %s", err) + } + } + } app.authJf, _ = jfapi.NewJellyfin(server, "jfa-go", app.version, "auth", "auth", common.NewTimeoutHandler("Jellyfin", server, true), cacheTimeout) app.loadStrftime() diff --git a/scss/bs4/bs4-jf.scss b/scss/bs4/bs4-jf.scss index 73146ac..a9d470c 100644 --- a/scss/bs4/bs4-jf.scss +++ b/scss/bs4/bs4-jf.scss @@ -1,145 +1,4 @@ -$jf-blue: rgb(0, 164, 220); -$jf-blue-hover: rgba(0, 164, 220, 0.2); -$jf-blue-focus: rgb(12, 176, 232); -$jf-blue-light: #4bb3dd; - -$jf-red: rgb(204, 0, 0); -$jf-red-light: #e12026; -$jf-yellower: #ffc107; -$jf-yellow: #e1b222; -$jf-orange: #ff870f; -$jf-green: #6fbd45; -$jf-green-dark: #008040; - - -$jf-black: #101010; // 16 16 16 -$jf-gray-90: #202020; // 32 32 32 -$jf-gray-80: #242424; // jf-card 36 36 36 -$jf-gray-70: #292929; // jf-input 41 41 41 -$jf-gray-60: #303030; // jf-button 48 48 48 -$jf-gray-50: #383838; // jf-button-focus 56 56 56 -$jf-text-bold: rgba(255, 255, 255, 0.87); -$jf-text-primary: rgba(255, 255, 255, 0.8); -$jf-text-secondary: rgb(153, 153, 153); - -$primary: $jf-blue; -$secondary: $jf-gray-50; -$success: $jf-green-dark; -$danger: $jf-red-light; -$light: $jf-text-primary; -$dark: $jf-gray-90; -$info: $jf-yellow; -$warning: $jf-yellower; - - - -$enable-gradients: false; -$enable-shadows: false; - -$enable-rounded: false; -$body-bg: $jf-black; -$body-color: $jf-text-primary; -$border-color: $jf-gray-60; -$component-active-color: $jf-text-bold; -$component-active-bg: $jf-blue-focus; -$text-muted: $jf-text-secondary; -$link-color: $jf-blue-focus; -$btn-link-disabled-color: $jf-text-secondary; -$input-bg: $jf-gray-90; -$input-color: $jf-text-primary; -$input-focus-bg: $jf-gray-60; -$input-focus-border-color: $jf-blue-focus; -$input-disabled-bg: $jf-gray-70; -input:disabled { - color: $text-muted; -} -$input-border-color: $jf-gray-60; -$input-placeholder-color: $text-muted; - -$form-check-input-bg: $jf-gray-60; -$form-check-input-border: $jf-gray-50; -$form-check-input-checked-color: $jf-blue-focus; -$form-check-input-checked-bg-color: $jf-blue-hover; - -$input-group-addon-bg: $input-bg; - -$form-select-disabled-color: $jf-text-secondary; -$form-select-disabled-bg: $input-disabled-bg; -$form-select-indicator-color: $jf-gray-50; - -$card-bg: $jf-gray-80; -$card-border-color: null; - -$tooltip-color: $jf-text-bold; -$tooltip-bg: $jf-gray-50; - -$modal-content-bg: $jf-gray-80; -$modal-content-border-color: $jf-gray-50; -$modal-header-border-color: null; -$modal-footer-border-color: null; - -$list-group-bg: $card-bg; -$list-group-border-color: $jf-gray-50; -$list-group-hover-bg: $jf-blue-hover; -$list-group-active-bg: $jf-blue-focus; -$list-group-action-color: $jf-text-primary; -$list-group-action-hover-color: $jf-text-bold; -$list-group-action-active-color: $jf-text-bold; -$list-group-action-active-bg: $jf-blue-focus; - -// idk why but i had to put these above and below the import -.list-group-item-danger { - color: $jf-text-bold; - background-color: $danger; -} - -.list-group-item-success { - color: $jf-text-bold; - background-color: $success; -} - +@import "../jf-pre.scss"; @import "../../node_modules/bootstrap4/scss/bootstrap"; - -.btn-primary, .btn-outline-primary:hover, .btn-outline-primary:active { - color: $jf-text-bold; -} - -.close { - color: $jf-text-secondary; -} - -.close:hover, .close:active { - color: $jf-text-primary; -} - -.icon-button { - color: $text-muted; -} - -.icon-button:hover { - color: $jf-text-bold; -} - -.icon-button { - color: $text-muted; -} - -.text-bright { - color: $jf-text-bold; -} - -.list-group-item-danger { - color: $jf-text-bold; - background-color: $danger; -} - -.list-group-item-success { - color: $jf-text-bold; - background-color: $success; -} - -.nav-link:hover { - background-color: $jf-blue-hover; -} - +@import "../jf-post.scss"; @import "../base.scss"; diff --git a/scss/bs5/bs5-jf.scss b/scss/bs5/bs5-jf.scss index ebcafde..6b4a353 100644 --- a/scss/bs5/bs5-jf.scss +++ b/scss/bs5/bs5-jf.scss @@ -1,149 +1,7 @@ -$jf-blue: rgb(0, 164, 220); -$jf-blue-hover: rgba(0, 164, 220, 0.2); -$jf-blue-focus: rgb(12, 176, 232); -$jf-blue-light: #4bb3dd; - -$jf-red: rgb(204, 0, 0); -$jf-red-light: #e12026; -$jf-yellower: #ffc107; -$jf-yellow: #e1b222; -$jf-orange: #ff870f; -$jf-green: #6fbd45; -$jf-green-dark: #008040; - - -$jf-black: #101010; // 16 16 16 -$jf-gray-90: #202020; // 32 32 32 -$jf-gray-80: #242424; // jf-card 36 36 36 -$jf-gray-70: #292929; // jf-input 41 41 41 -$jf-gray-60: #303030; // jf-button 48 48 48 -$jf-gray-50: #383838; // jf-button-focus 56 56 56 -$jf-text-bold: rgba(255, 255, 255, 0.87); -$jf-text-primary: rgba(255, 255, 255, 0.8); -$jf-text-secondary: rgb(153, 153, 153); - -$primary: $jf-blue; -$secondary: $jf-gray-50; -$success: $jf-green-dark; -$danger: $jf-red-light; -$light: $jf-text-primary; -$dark: $jf-gray-90; -$info: $jf-yellow; -$warning: $jf-yellower; - - - -$enable-gradients: false; -$enable-shadows: false; - -$enable-rounded: false; -$body-bg: $jf-black; -$body-color: $jf-text-primary; -$border-color: $jf-gray-60; -$component-active-color: $jf-text-bold; -$component-active-bg: $jf-blue-focus; -$text-muted: $jf-text-secondary; -$link-color: $jf-blue-focus; -$btn-link-disabled-color: $jf-text-secondary; -$input-bg: $jf-gray-90; -$input-color: $jf-text-primary; -$input-focus-bg: $jf-gray-60; -$input-focus-border-color: $jf-blue-focus; -$input-disabled-bg: $jf-gray-70; -input:disabled { - color: $text-muted; -} -$input-border-color: $jf-gray-60; -$input-placeholder-color: $text-muted; - -$form-check-input-bg: $jf-gray-60; -$form-check-input-border: $jf-gray-50; -$form-check-input-checked-color: $jf-blue-focus; -$form-check-input-checked-bg-color: $jf-blue-hover; - -$input-group-addon-bg: $input-bg; - -$form-select-disabled-color: $jf-text-secondary; -$form-select-disabled-bg: $input-disabled-bg; -$form-select-indicator-color: $jf-gray-50; - -$card-bg: $jf-gray-80; -$card-border-color: null; - -$tooltip-color: $jf-text-bold; -$tooltip-bg: $jf-gray-50; - -$modal-content-bg: $jf-gray-80; -$modal-content-border-color: $jf-gray-50; -$modal-header-border-color: null; -$modal-footer-border-color: null; - -$list-group-bg: $card-bg; -$list-group-border-color: $jf-gray-50; -$list-group-hover-bg: $jf-blue-hover; -$list-group-active-bg: $jf-blue-focus; -$list-group-action-color: $jf-text-primary; -$list-group-action-hover-color: $jf-text-bold; -$list-group-action-active-color: $jf-text-bold; -$list-group-action-active-bg: $jf-blue-focus; - -// idk why but i had to put these above and below the import -.list-group-item-danger { - color: $jf-text-bold; - background-color: $danger; -} - -.list-group-item-success { - color: $jf-text-bold; - background-color: $success; -} - -@import "../../node_modules/bootstrap/scss/bootstrap"; - -.btn-primary, .btn-outline-primary:hover, .btn-outline-primary:active { - color: $jf-text-bold; -} - -.close { - color: $jf-text-secondary; -} - -.close:hover, .close:active { - color: $jf-text-primary; -} - -.icon-button { - color: $text-muted; -} - -.icon-button:hover { - color: $jf-text-bold; -} - -.icon-button:active { - color: $text-muted; -} - -.text-bright { - color: $jf-text-bold; -} - -.list-group-item-danger { - color: $jf-text-bold; - background-color: $danger; -} - -.list-group-item-success { - color: $jf-text-bold; - background-color: $success; -} - -.nav-link:hover { - background-color: $jf-blue-hover; -} - .btn-close { filter: invert(80%); } - +@import "../jf-pre.scss"; +@import "../../node_modules/bootstrap/scss/bootstrap"; +@import "../jf-post.scss"; @import "../base.scss"; diff --git a/scss/jf-post.scss b/scss/jf-post.scss new file mode 100644 index 0000000..5a82ff1 --- /dev/null +++ b/scss/jf-post.scss @@ -0,0 +1,41 @@ +.btn-primary, .btn-outline-primary:hover, .btn-outline-primary:active { + color: $jf-text-bold; +} + +.close { + color: $jf-text-secondary; +} + +.close:hover, .close:active { + color: $jf-text-primary; +} + +.icon-button { + color: $text-muted; +} + +.icon-button:hover { + color: $jf-text-bold; +} + +.icon-button:active { + color: $text-muted; +} + +.text-bright { + color: $jf-text-bold; +} + +.list-group-item-danger { + color: $jf-text-bold; + background-color: $danger; +} + +.list-group-item-success { + color: $jf-text-bold; + background-color: $success; +} + +.nav-link:hover { + background-color: $jf-blue-hover; +} diff --git a/scss/jf-pre.scss b/scss/jf-pre.scss new file mode 100644 index 0000000..205e77d --- /dev/null +++ b/scss/jf-pre.scss @@ -0,0 +1,101 @@ +$jf-blue: rgb(0, 164, 220); +$jf-blue-hover: rgba(0, 164, 220, 0.2); +$jf-blue-focus: rgb(12, 176, 232); +$jf-blue-light: #4bb3dd; + +$jf-red: rgb(204, 0, 0); +$jf-red-light: #e12026; +$jf-yellower: #ffc107; +$jf-yellow: #e1b222; +$jf-orange: #ff870f; +$jf-green: #6fbd45; +$jf-green-dark: #008040; + + +$jf-black: #101010; // 16 16 16 +$jf-gray-90: #202020; // 32 32 32 +$jf-gray-80: #242424; // jf-card 36 36 36 +$jf-gray-70: #292929; // jf-input 41 41 41 +$jf-gray-60: #303030; // jf-button 48 48 48 +$jf-gray-50: #383838; // jf-button-focus 56 56 56 +$jf-text-bold: rgba(255, 255, 255, 0.87); +$jf-text-primary: rgba(255, 255, 255, 0.8); +$jf-text-secondary: rgb(153, 153, 153); + +$primary: $jf-blue; +$secondary: $jf-gray-50; +$success: $jf-green-dark; +$danger: $jf-red-light; +$light: $jf-text-primary; +$dark: $jf-gray-90; +$info: $jf-yellow; +$warning: $jf-yellower; + + + +$enable-gradients: false; +$enable-shadows: false; + +$enable-rounded: false; +$body-bg: $jf-black; +$body-color: $jf-text-primary; +$border-color: $jf-gray-60; +$component-active-color: $jf-text-bold; +$component-active-bg: $jf-blue-focus; +$text-muted: $jf-text-secondary; +$link-color: $jf-blue-focus; +$btn-link-disabled-color: $jf-text-secondary; +$input-bg: $jf-gray-90; +$input-color: $jf-text-primary; +$input-focus-bg: $jf-gray-60; +$input-focus-border-color: $jf-blue-focus; +$input-disabled-bg: $jf-gray-70; +input:disabled { + color: $text-muted; +} +$input-border-color: $jf-gray-60; +$input-placeholder-color: $text-muted; + +$form-check-input-bg: $jf-gray-60; +$form-check-input-border: $jf-gray-50; +$form-check-input-checked-color: $jf-blue-focus; +$form-check-input-checked-bg-color: $jf-blue-hover; + +$input-group-addon-bg: $input-bg; + +$form-select-disabled-color: $jf-text-secondary; +$form-select-disabled-bg: $input-disabled-bg; +$form-select-indicator-color: $jf-gray-50; + +$card-bg: $jf-gray-80; +$card-border-color: null; + +$tooltip-color: $jf-text-bold; +$tooltip-bg: $jf-gray-50; + +$modal-content-bg: $jf-gray-80; +$modal-content-border-color: $jf-gray-50; +$modal-header-border-color: null; +$modal-footer-border-color: null; + +$list-group-bg: $card-bg; +$list-group-border-color: $jf-gray-50; +$list-group-hover-bg: $jf-blue-hover; +$list-group-active-bg: $jf-blue-focus; +$list-group-action-color: $jf-text-primary; +$list-group-action-hover-color: $jf-text-bold; +$list-group-action-active-color: $jf-text-bold; +$list-group-action-active-bg: $jf-blue-focus; + +// idk why but i had to put these above and below the import +.list-group-item-danger { + color: $jf-text-bold; + background-color: $danger; +} + +.list-group-item-success { + color: $jf-text-bold; + background-color: $success; +} + +// @import "../../node_modules/bootstrap/scss/bootstrap"; diff --git a/storage.go b/storage.go index b8aab62..b21e705 100644 --- a/storage.go +++ b/storage.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "log" "strconv" + "strings" "time" ) @@ -190,3 +191,23 @@ 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) { + jfUsers, status, err := app.jf.GetUsers(false) + if status != 200 || err != nil { + return nil, status, err + } + newEmails := map[string]interface{}{} + for _, user := range jfUsers { + unstripped := user["Id"].(string) + stripped := strings.ReplaceAll(unstripped, "-", "") + email, ok := old[stripped] + if ok { + newEmails[unstripped] = email + } + } + return newEmails, status, err +}