From 976d54371184833ab109263e713c293f391ca734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Hilligs=C3=B8e?= Date: Sun, 16 Feb 2025 16:38:32 +0100 Subject: [PATCH] Color printing most things now. mod update --- .github/workflows/release.yaml | 4 +-- cmd/kefw2/cmd/color_print.go | 12 +++++++ cmd/kefw2/cmd/config.go | 21 +++++++++++++ cmd/kefw2/cmd/config_speaker.go | 50 +++++++++++++++++++++++------- cmd/kefw2/cmd/eq_profile.go | 21 +++++++++++++ cmd/kefw2/cmd/maxvolume.go | 29 ++++++++++++++--- cmd/kefw2/cmd/mute.go | 35 ++++++++++++++++++--- cmd/kefw2/cmd/next_track.go | 28 ++++++++++++++--- cmd/kefw2/cmd/off.go | 27 ++++++++++++++-- cmd/kefw2/cmd/pause.go | 46 ++++++++++++++++++--------- cmd/kefw2/cmd/play.go | 37 ++++++++++++++++++---- cmd/kefw2/cmd/prevous_track.go | 28 ++++++++++++++--- cmd/kefw2/cmd/root.go | 37 +++++++++++++++------- cmd/kefw2/cmd/source.go | 28 +++++++++++++++-- cmd/kefw2/cmd/status.go | 55 +++++++++++++++++++++++++-------- cmd/kefw2/cmd/volume.go | 28 +++++++++++++++-- cmd/kefw2/kefw2.go | 2 +- go.mod | 10 +++--- go.sum | 24 ++++++-------- 19 files changed, 418 insertions(+), 104 deletions(-) create mode 100644 cmd/kefw2/cmd/color_print.go diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d4bb689..62d6dd6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,7 +9,7 @@ on: jobs: release: name: Release - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 @@ -18,7 +18,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: '1.24' check-latest: true - name: Release uses: goreleaser/goreleaser-action@v6 diff --git a/cmd/kefw2/cmd/color_print.go b/cmd/kefw2/cmd/color_print.go new file mode 100644 index 0000000..9b96403 --- /dev/null +++ b/cmd/kefw2/cmd/color_print.go @@ -0,0 +1,12 @@ +package cmd + +import ( + "github.com/fatih/color" +) + +var ( + headerPrinter = color.New(color.FgCyan) // .Add(color.Bold) + contentPrinter = color.New(color.FgYellow).Add(color.Bold) + taskConpletedPrinter = color.New(color.FgGreen).Add(color.Bold) + errorPrinter = color.New(color.FgRed).Add(color.Bold) +) diff --git a/cmd/kefw2/cmd/config.go b/cmd/kefw2/cmd/config.go index b5ff171..cac6bd7 100644 --- a/cmd/kefw2/cmd/config.go +++ b/cmd/kefw2/cmd/config.go @@ -1,3 +1,24 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( diff --git a/cmd/kefw2/cmd/config_speaker.go b/cmd/kefw2/cmd/config_speaker.go index 8f35e80..3de4ed2 100644 --- a/cmd/kefw2/cmd/config_speaker.go +++ b/cmd/kefw2/cmd/config_speaker.go @@ -1,3 +1,24 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( @@ -55,10 +76,11 @@ var speakerDiscoverCmd = &cobra.Command{ return } for _, speaker := range newSpeakers { - fmt.Printf("Found speaker: %s (%s)\n", speaker.Name, speaker.IPAddress) + headerPrinter.Print("Found speaker: ") + contentPrinter.Printf("%s (%s)\n", speaker.Name, speaker.IPAddress) if save { if err := addSpeaker(speaker.IPAddress); err != nil { - fmt.Printf("Error adding speaker (%s): %s\n", speaker.IPAddress, err) + errorPrinter.Printf("Error adding speaker (%s): %s\n", speaker.IPAddress, err) } } } @@ -71,7 +93,7 @@ var speakerAddCmd = &cobra.Command{ Long: `Add a speaker`, Run: func(cmd *cobra.Command, args []string) { if err := addSpeaker(args[0]); err != nil { - fmt.Printf("Error adding speaker (%s): %s\n", args[0], err) + errorPrinter.Printf("Error adding speaker (%s): %s\n", args[0], err) } }, } @@ -83,11 +105,11 @@ var speakerRemoveCmd = &cobra.Command{ Long: `Remove a speaker`, Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - fmt.Println("Error: missing speaker IP address") + errorPrinter.Println("Error: missing speaker IP address") return } if err := removeSpeaker(args[0]); err != nil { - fmt.Printf("Error removing speaker (%s): %s\n", args[0], err) + errorPrinter.Printf("Error removing speaker (%s): %s\n", args[0], err) } }, } @@ -101,9 +123,9 @@ var speakerListCmd = &cobra.Command{ defaultSpeakerIP := viper.GetString("defaultSpeaker") for _, speaker := range speakers { if speaker.IPAddress == defaultSpeakerIP { - fmt.Printf("%s (%s) [default]\n", speaker.Name, speaker.IPAddress) + contentPrinter.Printf("%s (%s) [default]\n", speaker.Name, speaker.IPAddress) } else { - fmt.Printf("%s (%s)\n", speaker.Name, speaker.IPAddress) + contentPrinter.Printf("%s (%s)\n", speaker.Name, speaker.IPAddress) } } }, @@ -116,11 +138,12 @@ var speakerSetDefaultCmd = &cobra.Command{ Long: "Set default speaker", Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { - fmt.Printf("Default speaker is: %s (%s)\n", defaultSpeaker.Name, defaultSpeaker.IPAddress) + headerPrinter.Print("Default speaker: ") + contentPrinter.Printf("%s (%s)\n", defaultSpeaker.Name, defaultSpeaker.IPAddress) return } if err := setDefaultSpeaker(args[0]); err != nil { - fmt.Printf("Error setting default speaker (%s): %s\n", args[0], err) + errorPrinter.Printf("Error setting default speaker (%s): %s\n", args[0], err) } }, ValidArgsFunction: ConfiguredSpeakersCompletion, @@ -136,10 +159,13 @@ func addSpeaker(host string) (err error) { } speakers = append(speakers, speaker) viper.Set("speakers", speakers) - fmt.Printf("Added speaker: %s (%s)\n", speaker.Name, speaker.IPAddress) + taskConpletedPrinter.Print("Added speaker: ") + contentPrinter.Printf("%s (%s)\n", speaker.Name, speaker.IPAddress) + if len(speakers) == 1 { viper.Set("defaultSpeaker", speaker.IPAddress) - fmt.Printf("Set default speaker: %s (%s)\n", speaker.Name, speaker.IPAddress) + taskConpletedPrinter.Printf("Saved default speaker: ") + contentPrinter.Printf("%s (%s)\n", speaker.Name, speaker.IPAddress) } viper.WriteConfig() return @@ -150,7 +176,7 @@ func removeSpeaker(host string) (err error) { if speaker.IPAddress == host { speakers = append(speakers[:i], speakers[i+1:]...) viper.Set("speakers", speakers) - fmt.Printf("Removed speaker: %s (%s)\n", speaker.Name, speaker.IPAddress) + taskConpletedPrinter.Printf("Removed speaker: %s (%s)\n", speaker.Name, speaker.IPAddress) viper.WriteConfig() return } diff --git a/cmd/kefw2/cmd/eq_profile.go b/cmd/kefw2/cmd/eq_profile.go index d183fea..78502ba 100644 --- a/cmd/kefw2/cmd/eq_profile.go +++ b/cmd/kefw2/cmd/eq_profile.go @@ -1,3 +1,24 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( diff --git a/cmd/kefw2/cmd/maxvolume.go b/cmd/kefw2/cmd/maxvolume.go index bff735e..81d7b54 100644 --- a/cmd/kefw2/cmd/maxvolume.go +++ b/cmd/kefw2/cmd/maxvolume.go @@ -1,7 +1,27 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( - "fmt" "os" "github.com/spf13/cobra" @@ -17,17 +37,18 @@ var maxVolumeCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { volume, _ := currentSpeaker.GetMaxVolume() - fmt.Printf("Max volume is: %d%%\n", volume) + headerPrinter.Print("Max volume: ") + contentPrinter.Printf("%d%%\n", volume) return } volume, err := parseVolume(args[0]) if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } err = currentSpeaker.SetMaxVolume(volume) if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } }, diff --git a/cmd/kefw2/cmd/mute.go b/cmd/kefw2/cmd/mute.go index 0340a42..aa2bdd9 100644 --- a/cmd/kefw2/cmd/mute.go +++ b/cmd/kefw2/cmd/mute.go @@ -1,3 +1,24 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( @@ -9,19 +30,25 @@ import ( // muteCmd toggles the mute state of the speakers var muteCmd = &cobra.Command{ - Use: "mute", + Use: "mute on/off", Short: "Get or adjust the mute state of the speakers", Long: `Get or adjust the mute state of the speakers`, Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { mute, _ := currentSpeaker.IsMuted() - fmt.Printf("Speakers are muted: %t\n", mute) + if mute { + headerPrinter.Print("Speakers are ") + contentPrinter.Println("muted") + } else { + headerPrinter.Print("Speakers are ") + contentPrinter.Println("not muted") + } return } mute, err := parseMuteArg(args[0]) if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } if mute { @@ -30,7 +57,7 @@ var muteCmd = &cobra.Command{ err = currentSpeaker.Unmute() } if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } }, diff --git a/cmd/kefw2/cmd/next_track.go b/cmd/kefw2/cmd/next_track.go index 5e11843..1414105 100644 --- a/cmd/kefw2/cmd/next_track.go +++ b/cmd/kefw2/cmd/next_track.go @@ -1,7 +1,27 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( - "fmt" "os" "github.com/spf13/cobra" @@ -16,16 +36,16 @@ var nextTrackCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { canControlPlayback, err := currentSpeaker.CanControlPlayback() if err != nil { - fmt.Printf("Can't skip track: %s\n", err.Error()) + errorPrinter.Printf("Can't skip track: %s\n", err.Error()) os.Exit(1) } if !canControlPlayback { - fmt.Println("Not on WiFi/BT source.") + errorPrinter.Println("Not on WiFi/BT source.") os.Exit(0) } err = currentSpeaker.NextTrack() if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } }, diff --git a/cmd/kefw2/cmd/off.go b/cmd/kefw2/cmd/off.go index 67bf74a..6e2b183 100644 --- a/cmd/kefw2/cmd/off.go +++ b/cmd/kefw2/cmd/off.go @@ -1,8 +1,27 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( - "fmt" - "github.com/spf13/cobra" ) @@ -15,8 +34,10 @@ var offCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { err := currentSpeaker.PowerOff() if err != nil { - fmt.Println(err) + errorPrinter.Println(err) } + taskConpletedPrinter.Print("Speakers are now ") + contentPrinter.Println("off") }, } diff --git a/cmd/kefw2/cmd/pause.go b/cmd/kefw2/cmd/pause.go index 00b1973..c49d233 100644 --- a/cmd/kefw2/cmd/pause.go +++ b/cmd/kefw2/cmd/pause.go @@ -1,7 +1,27 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( - "fmt" "os" "github.com/spf13/cobra" @@ -10,30 +30,28 @@ import ( // muteCmd toggles the mute state of the speakers var pauseCmd = &cobra.Command{ Use: "pause", - Short: "Pause playback when on WiFi source", - Long: `Pause playback when on WiFi source`, + Short: "Pause playback when on WiFi/BT source", + Long: `Pause playback when on WiFi/BT source`, Args: cobra.MaximumNArgs(0), Run: func(cmd *cobra.Command, args []string) { canControlPlayback, err := currentSpeaker.CanControlPlayback() if err != nil { - fmt.Printf("Can't pause speaker: %s\n", err.Error()) + errorPrinter.Println(err) os.Exit(1) } if !canControlPlayback { - fmt.Println("Not on WiFi/BT source.") + errorPrinter.Println("Can't pause speaker: Not on WiFi/BT source.") os.Exit(0) } if isPlaying, err := currentSpeaker.IsPlaying(); err != nil { - fmt.Println(err) - os.Exit(1) - } else if !isPlaying { - fmt.Println("Not playing, not pausing") - os.Exit(0) - } - err = currentSpeaker.PlayPause() - if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) + } else if isPlaying { + err = currentSpeaker.PlayPause() + if err != nil { + errorPrinter.Println(err) + os.Exit(1) + } } }, } diff --git a/cmd/kefw2/cmd/play.go b/cmd/kefw2/cmd/play.go index d05c548..dec46b8 100644 --- a/cmd/kefw2/cmd/play.go +++ b/cmd/kefw2/cmd/play.go @@ -1,7 +1,27 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( - "fmt" "os" "github.com/spf13/cobra" @@ -16,17 +36,22 @@ var playCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { canControlPlayback, err := currentSpeaker.CanControlPlayback() if err != nil { - fmt.Printf("Can't query source: %s\n", err.Error()) + errorPrinter.Printf("Can't query source: %s\n", err.Error()) os.Exit(1) } if !canControlPlayback { - fmt.Println("Not on WiFi/BT source.") + headerPrinter.Println("Can only play on WiFi/BT source.") os.Exit(0) } - err = currentSpeaker.PlayPause() - if err != nil { - fmt.Println(err) + if isPlaying, err := currentSpeaker.IsPlaying(); err != nil { + errorPrinter.Println(err) os.Exit(1) + } else if !isPlaying { + err = currentSpeaker.PlayPause() + if err != nil { + errorPrinter.Println(err) + os.Exit(1) + } } }, } diff --git a/cmd/kefw2/cmd/prevous_track.go b/cmd/kefw2/cmd/prevous_track.go index 05f55f6..ec200b8 100644 --- a/cmd/kefw2/cmd/prevous_track.go +++ b/cmd/kefw2/cmd/prevous_track.go @@ -1,7 +1,27 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( - "fmt" "os" "github.com/spf13/cobra" @@ -17,16 +37,16 @@ var previousTrackCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { canControlPlayback, err := currentSpeaker.CanControlPlayback() if err != nil { - fmt.Printf("Can't skip back: %s\n", err.Error()) + errorPrinter.Printf("Can't skip back: %s\n", err.Error()) os.Exit(1) } if !canControlPlayback { - fmt.Println("Not on WiFi/BT source.") + errorPrinter.Println("Not on WiFi/BT source.") os.Exit(0) } err = currentSpeaker.PreviousTrack() if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } }, diff --git a/cmd/kefw2/cmd/root.go b/cmd/kefw2/cmd/root.go index 2801d4d..c714c36 100644 --- a/cmd/kefw2/cmd/root.go +++ b/cmd/kefw2/cmd/root.go @@ -1,5 +1,5 @@ /* -Copyright © 2023-2024 Jens Hilligsøe +Copyright © 2023-2025 Jens Hilligsøe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -58,16 +58,29 @@ var VersionCmd = &cobra.Command{ Long: "Print the version number of kefw2", Run: func(cmd *cobra.Command, args []string) { fmt.Println("kefw2: Command line tool for controlling KEF's W2 platform speakers") + var GitCommit string + var BuildDate string if info, ok := debug.ReadBuildInfo(); ok { + modified := false for _, v := range info.Settings { + errorPrinter.Print(v.Key) switch v.Key { case "vcs.revision": - fmt.Printf("Version: %s\n", v.Value) + GitCommit = v.Value case "vcs.time": - fmt.Printf("Build date: %s\n", v.Value) + BuildDate = v.Value + case "vcs.modified": + modified = true + } + if modified { + GitCommit += "-dirty" } } } + headerPrinter.Print("Version: ") + contentPrinter.Printf("%s\n", GitCommit) + headerPrinter.Print("Build date: ") + contentPrinter.Printf("%s\n", BuildDate) }, } @@ -91,11 +104,12 @@ func Execute() { } if currentSpeaker == nil && len(speakers) == 0 { - fmt.Fprintf(os.Stderr, "No speakers configured. Please configure a speaker first:\n") - fmt.Fprintf(os.Stderr, "- Discover speakers automatically:\n") - fmt.Fprintf(os.Stderr, " kefw2 config speaker discover --save\n") - fmt.Fprintf(os.Stderr, "- Manually add a speaker:\n") - fmt.Fprintf(os.Stderr, " kefw2 config speaker add IP_ADDRESS\n") + errorPrinter.Fprintf(os.Stderr, "No speakers configured. Please configure a speaker first:\n") + errorPrinter.Fprintf(os.Stderr, "Please configure a speaker first:\n") + errorPrinter.Fprintf(os.Stderr, "- Discover speakers automatically:\n") + errorPrinter.Fprintf(os.Stderr, " kefw2 config speaker discover --save\n") + errorPrinter.Fprintf(os.Stderr, "- Manually add a speaker:\n") + errorPrinter.Fprintf(os.Stderr, " kefw2 config speaker add IP_ADDRESS\n") os.Exit(1) } } @@ -154,7 +168,8 @@ func initConfig() { } // Unmarshal speakers if err := viper.UnmarshalKey("speakers", &speakers); err != nil { - log.Fatal(err) + errorPrinter.Println("Error unmarshalling speakers:", err) + os.Exit(1) } // Unmarshal default speaker and set it up defaultSpeakerIP := viper.GetString("defaultSpeaker") @@ -170,14 +185,14 @@ func initConfig() { defaultSpeaker = &speakers[0] viper.Set("defaultSpeaker", defaultSpeaker.IPAddress) viper.WriteConfig() - fmt.Printf("No default speaker was set. Using first available speaker as default: %s (%s)\n", + taskConpletedPrinter.Printf("No default speaker was set. Using first available speaker as default: %s (%s)\n", defaultSpeaker.Name, defaultSpeaker.IPAddress) } if currentSpeakerParam != "" { newSpeaker, err := kefw2.NewSpeaker(currentSpeakerParam) if err != nil { - fmt.Printf("Hmm, %s does not look like it is a KEF W2 speaker:\n%s\n", currentSpeakerParam, err.Error()) + errorPrinter.Printf("Hmm, %s does not look like it is a KEF W2 speaker:\n%s\n", currentSpeakerParam, err.Error()) } currentSpeaker = &newSpeaker } else { diff --git a/cmd/kefw2/cmd/source.go b/cmd/kefw2/cmd/source.go index bcb2a8c..9dbe24b 100644 --- a/cmd/kefw2/cmd/source.go +++ b/cmd/kefw2/cmd/source.go @@ -1,3 +1,24 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( @@ -18,17 +39,18 @@ var sourceCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { source, _ := currentSpeaker.Source() - fmt.Printf("Source is: %s\n", source.String()) + headerPrinter.Print("Source: ") + contentPrinter.Printf("%s\n", source.String()) return } source, err := parseSource(args[0]) if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } err = currentSpeaker.SetSource(source) if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } }, diff --git a/cmd/kefw2/cmd/status.go b/cmd/kefw2/cmd/status.go index 82e9dfe..12f69f3 100644 --- a/cmd/kefw2/cmd/status.go +++ b/cmd/kefw2/cmd/status.go @@ -1,3 +1,24 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( @@ -21,42 +42,48 @@ var statusCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { source, err := currentSpeaker.Source() if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } canControlPlayback, err := currentSpeaker.CanControlPlayback() if err != nil { - fmt.Printf("Can't show status: %s\n", err.Error()) + errorPrinter.Printf("Can't show status: %s\n", err.Error()) os.Exit(1) } if canControlPlayback { pd, err := currentSpeaker.PlayerData() if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } if playstate, err := currentSpeaker.IsPlaying(); err != nil { - fmt.Println("error getting playstate:", err) + errorPrinter.Println("error getting playstate:", err) } else { if playstate { playTime, _ := currentSpeaker.SongProgress() // Minimalistic output - fmt.Println("Source:", source) + headerPrinter.Print("Source: ") + contentPrinter.Println(source) if source == kefw2.SourceWiFi { - fmt.Println("Audio Transport:", pd.MediaRoles.Title) + headerPrinter.Print("Audio Transport: ") + contentPrinter.Println(pd.MediaRoles.Title) if pd.TrackRoles.MediaData.MetaData.Artist != "" { - fmt.Println("Artist:", pd.TrackRoles.MediaData.MetaData.Artist) + headerPrinter.Print("Artist: ") + contentPrinter.Println(pd.TrackRoles.MediaData.MetaData.Artist) } if pd.TrackRoles.MediaData.MetaData.Album != "" { - fmt.Println("Album:", pd.TrackRoles.MediaData.MetaData.Album) + headerPrinter.Print("Album: ") + contentPrinter.Println(pd.TrackRoles.MediaData.MetaData.Album) } if pd.TrackRoles.Title != "" { - fmt.Println("Track:", pd.TrackRoles.Title) + headerPrinter.Print("Track: ") + contentPrinter.Println(pd.TrackRoles.Title) } + headerPrinter.Print("Duration: ") if pd.Status.Duration == 0 { - fmt.Printf("Duration: %s\n", playTime) + contentPrinter.Printf("%s\n", playTime) } else { - fmt.Printf("Duration: %s/%s\n", playTime, pd.Status) + contentPrinter.Printf("%s/%s\n", playTime, pd.Status) } } // Not so minimalistic output @@ -65,11 +92,13 @@ var statusCmd = &cobra.Command{ fmt.Println() // newline so shell prompt does not appear to the right of the image } } else { - fmt.Println("Audio Transport: stopped") + headerPrinter.Print("Audio Transport: ") + contentPrinter.Println("Stopped") } } } else { - fmt.Println("Source:", source) + headerPrinter.Print("Source: ") + contentPrinter.Println(source) } }, } diff --git a/cmd/kefw2/cmd/volume.go b/cmd/kefw2/cmd/volume.go index a9e3dbb..1145b61 100644 --- a/cmd/kefw2/cmd/volume.go +++ b/cmd/kefw2/cmd/volume.go @@ -1,3 +1,24 @@ +/* +Copyright © 2023-2025 Jens Hilligsøe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ package cmd import ( @@ -17,17 +38,18 @@ var volumeCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { if len(args) != 1 { volume, _ := currentSpeaker.GetVolume() - fmt.Printf("Volume is: %d%%\n", volume) + headerPrinter.Printf("Volume is: ") + contentPrinter.Printf("%d%%\n", volume) return } volume, err := parseVolume(args[0]) if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } err = currentSpeaker.SetVolume(volume) if err != nil { - fmt.Println(err) + errorPrinter.Println(err) os.Exit(1) } }, diff --git a/cmd/kefw2/kefw2.go b/cmd/kefw2/kefw2.go index 120aa2e..6fddb34 100644 --- a/cmd/kefw2/kefw2.go +++ b/cmd/kefw2/kefw2.go @@ -1,5 +1,5 @@ /* -Copyright © 2023-2024 Jens Hilligsøe +Copyright © 2023-2025 Jens Hilligsøe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/go.mod b/go.mod index 2081372..124e6bc 100644 --- a/go.mod +++ b/go.mod @@ -7,19 +7,19 @@ toolchain go1.23.6 require ( github.com/brutella/dnssd v1.2.14 github.com/brutella/hap v0.0.35 + github.com/fatih/color v1.18.0 github.com/hilli/icat v0.0.6 github.com/ivanpirog/coloredcobra v1.0.1 github.com/joho/godotenv v1.5.1 github.com/k0kubun/pp v3.0.1+incompatible github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v1.8.1 + github.com/spf13/cobra v1.9.0 github.com/spf13/viper v1.19.0 ) require ( github.com/BourgeoisBear/rasterm v1.1.2-0.20250103192908-b3632033a926 // indirect github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect - github.com/fatih/color v1.18.0 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/go-chi/chi v1.5.5 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -48,15 +48,15 @@ require ( github.com/xiam/to v0.0.0-20200126224905-d60d31e03561 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.33.0 // indirect - golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 // indirect + golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect golang.org/x/image v0.24.0 // indirect golang.org/x/mod v0.23.0 // indirect - golang.org/x/net v0.34.0 // indirect + golang.org/x/net v0.35.0 // indirect golang.org/x/sync v0.11.0 // indirect golang.org/x/sys v0.30.0 // indirect golang.org/x/term v0.29.0 // indirect golang.org/x/text v0.22.0 // indirect - golang.org/x/tools v0.29.0 // indirect + golang.org/x/tools v0.30.0 // indirect gopkg.in/Regis24GmbH/go-diacritics.v2 v2.0.3 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 3ce83bf..0b73f2f 100644 --- a/go.sum +++ b/go.sum @@ -7,7 +7,7 @@ github.com/brutella/dnssd v1.2.14/go.mod h1:tG4GE8orv6+irE5rdsNgb6MJSxm6cyMUKdC5 github.com/brutella/hap v0.0.35 h1:9J6jWnrlnZGJIdskYdkRt8EGfEoIe2sMqc6qBNQTnAM= github.com/brutella/hap v0.0.35/go.mod h1:vWJ+URAmB9aEXZ6bWeqO9iHwz+pcb89eR1pNYK2ZAUM= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -26,8 +26,6 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hilli/icat v0.0.5 h1:0xhPrAlPJFr/HiAh7LiRvmnuJXw3bpABawrqR3e6t5M= -github.com/hilli/icat v0.0.5/go.mod h1:Q4FS+ChUjlod7mgeyYMGWcF9LpJcqAXw8O27oBDUZ7g= github.com/hilli/icat v0.0.6 h1:oAHDI40pdR75JM/+R3cG6Jhbmsb5i53Uao53kdcgwmg= github.com/hilli/icat v0.0.6/go.mod h1:Q4FS+ChUjlod7mgeyYMGWcF9LpJcqAXw8O27oBDUZ7g= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -84,8 +82,8 @@ github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4 github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/cobra v1.9.0 h1:Py5fIuq/lJsRYxcxfOtsJqpmwJWCMOUy2tMJYV8TNHE= +github.com/spf13/cobra v1.9.0/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -128,14 +126,10 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c h1:KL/ZBHXgKGVmuZBZ01Lt57yE5ws8ZPSkkihmEyq7FXc= -golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= -golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 h1:qNgPs5exUA+G0C96DrPwNrvLSj7GT/9D+3WMWUcUg34= -golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= +golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg= +golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -155,8 +149,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -219,8 +213,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= -golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= -golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/Regis24GmbH/go-diacritics.v2 v2.0.3 h1:rz88vn1OH2B9kKorR+QCrcuw6WbizVwahU2Y9Q09xqU= gopkg.in/Regis24GmbH/go-diacritics.v2 v2.0.3/go.mod h1:vJmfdx2L0+30M90zUd0GCjLV14Ip3ZgWR5+MV1qljOo=