From 244bfa53290f0fef010627643a67df26c896ffa6 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 9 Aug 2024 20:47:28 +0200 Subject: [PATCH 1/3] chore: naming conventions --- api/cammie.go | 36 ++++++++++++++++++------------------ api/main.go | 6 +++--- api/spotify.go | 36 +++++++++++++++--------------------- 3 files changed, 36 insertions(+), 42 deletions(-) diff --git a/api/cammie.go b/api/cammie.go index 15cccf0..4f0754d 100644 --- a/api/cammie.go +++ b/api/cammie.go @@ -9,30 +9,30 @@ import ( gin "github.com/gin-gonic/gin" ) -// messageCammie struct -type messageCammie struct { +// cammieMessage struct +type cammieMessage struct { Message string `form:"message" json:"message" xml:"message" binding:"required"` } -// headerCammie struct -type headerCammie struct { +// cammieHeader struct +type cammieHeader struct { Name string `header:"X-Username"` IP string `header:"X-Real-IP"` } -var messages uint64 = 0 -var blockedNames = []string{"Paul-Henri Spaak"} // Blocekd names -var blockedIps = []string{} // Blocked IPs -var maxMessageLength = 200 // Maximum message length +var cammieCessages uint64 = 0 +var cammieBlockedNames = []string{"Paul-Henri Spaak"} // Blocked names +var cammieBlockedIps = []string{} // Blocked IPs +var cammieMaxMessageLength = 200 // Maximum message length -func getMessage(app *screen.ScreenApp, c *gin.Context) { - c.JSON(200, gin.H{"messages": messages}) +func cammieGetMessage(app *screen.ScreenApp, c *gin.Context) { + c.JSON(200, gin.H{"messages": cammieCessages}) } -func postMessage(app *screen.ScreenApp, c *gin.Context) { +func cammiePostMessage(app *screen.ScreenApp, c *gin.Context) { // Get structs - header := &headerCammie{} - message := &messageCammie{} + header := &cammieHeader{} + message := &cammieMessage{} // Check Header if err := c.ShouldBindHeader(header); err != nil { @@ -47,21 +47,21 @@ func postMessage(app *screen.ScreenApp, c *gin.Context) { } // Max message length - if len(message.Message) > maxMessageLength { - c.JSON(http.StatusBadRequest, gin.H{"error": "Message too long, maximum " + fmt.Sprint(maxMessageLength)}) + if len(message.Message) > cammieMaxMessageLength { + c.JSON(http.StatusBadRequest, gin.H{"error": "Message too long, maximum " + fmt.Sprint(cammieMaxMessageLength)}) return } // Check if sender is blocked and construct message var newMessage string if header.Name != "" { - if slices.Contains(blockedNames, header.Name) { + if slices.Contains(cammieBlockedNames, header.Name) { c.JSON(http.StatusOK, gin.H{"message": "Message received"}) return } newMessage = fmt.Sprintf("[%s[] %s", header.Name, message.Message) } else if header.IP != "" { - if slices.Contains(blockedIps, header.IP) { + if slices.Contains(cammieBlockedIps, header.IP) { c.JSON(http.StatusOK, gin.H{"message": "Message received"}) return } @@ -71,7 +71,7 @@ func postMessage(app *screen.ScreenApp, c *gin.Context) { } // Increment messages - messages++ + cammieCessages++ app.Cammie.Update(newMessage) diff --git a/api/main.go b/api/main.go index 81c019a..cc7eafd 100644 --- a/api/main.go +++ b/api/main.go @@ -24,11 +24,11 @@ func Start(screenApp *screen.ScreenApp) { // Routes // Cammie chat routes - r.GET("/message", handlerWrapper(screenApp, getMessage)) - r.POST("/message", handlerWrapper(screenApp, postMessage)) + r.GET("/message", handlerWrapper(screenApp, cammieGetMessage)) + r.POST("/message", handlerWrapper(screenApp, cammiePostMessage)) // Spotify routes - r.POST("/spotify", spotifyHandlerWrapper(screenApp)) + r.POST("/spotify", handlerWrapper(screenApp, spotifyGetMessage)) r.Run() } diff --git a/api/spotify.go b/api/spotify.go index d2e3b08..3691367 100644 --- a/api/spotify.go +++ b/api/spotify.go @@ -32,18 +32,12 @@ type spotifyTrackResponse struct { Artists []spotifyArtist `json:"artists"` } -var accessToken = "" -var expiresOn int64 = 0 -var clientID = "d385173507a54bca93cc3327c0c2f5d9" -var clientSecret = "8e78977c1ba54b90b17f9dcd6b301c37" - -func spotifyHandlerWrapper(app *screen.ScreenApp) func(*gin.Context) { - return func(ctx *gin.Context) { - spotifyHandler(app, ctx) - } -} +var spotifyAccessToken = "" +var spotifyExpiresOn int64 = 0 +var spotifyClientID = "d385173507a54bca93cc3327c0c2f5d9" +var spotifyClientSecret = "8e78977c1ba54b90b17f9dcd6b301c37" -func spotifyHandler(app *screen.ScreenApp, ctx *gin.Context) { +func spotifyGetMessage(app *screen.ScreenApp, ctx *gin.Context) { message := &spotifyMessage{} if err := ctx.ShouldBindJSON(message); err != nil { @@ -53,13 +47,13 @@ func spotifyHandler(app *screen.ScreenApp, ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{"track_id": "Track ID received"}) - if expiresOn < time.Now().Unix() { - if err := setAccessToken(); err != nil { + if spotifyExpiresOn < time.Now().Unix() { + if err := spotifySetAccessToken(); err != nil { fmt.Fprintf(os.Stderr, "Error: Unable to refresh spotify token: %s", err) } } - track, err := getTrackTitle(message.TrackID) + track, err := spotifyGetTrackTitle(message.TrackID) if err != nil { fmt.Fprintf(os.Stderr, "Error: Unable to get track information: %s", err) @@ -68,11 +62,11 @@ func spotifyHandler(app *screen.ScreenApp, ctx *gin.Context) { app.Spotify.Update(track) } -func setAccessToken() error { +func spotifySetAccessToken() error { data := url.Values{} data.Set("grant_type", "client_credentials") - data.Set("client_id", clientID) - data.Set("client_secret", clientSecret) + data.Set("client_id", spotifyClientID) + data.Set("client_secret", spotifyClientSecret) // Send the POST request resp, err := http.PostForm("https://accounts.spotify.com/api/token", data) @@ -91,20 +85,20 @@ func setAccessToken() error { return err } - accessToken = message.AccessToken - expiresOn = time.Now().Unix() + message.ExpiresIn + spotifyAccessToken = message.AccessToken + spotifyExpiresOn = time.Now().Unix() + message.ExpiresIn return nil } -func getTrackTitle(trackID string) (string, error) { +func spotifyGetTrackTitle(trackID string) (string, error) { url := fmt.Sprintf("https://api.spotify.com/v1/tracks/%s", trackID) req, err := http.NewRequest("GET", url, nil) if err != nil { return "", err } - req.Header.Set("Authorization", "Bearer "+accessToken) + req.Header.Set("Authorization", "Bearer "+spotifyAccessToken) client := &http.Client{} resp, err := client.Do(req) From e0ee906ac9130797314617ef1813bdfec5ef9146 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 9 Aug 2024 21:20:20 +0200 Subject: [PATCH 2/3] chore: use environment variables --- .gitignore | 4 +++- api/{main.go => api.go} | 0 api/cammie.go | 13 ++++++----- api/spotify.go | 22 ++++++++++++------ config.template.yaml | 7 ++++++ config/config.go | 44 +++++++++++++++++++++++++++++++++++ screen/graph1.go | 23 ------------------ screen/{main.go => screen.go} | 8 +++---- screen/tap.go | 23 ++++++++++++++++++ utils/utils.go | 25 ++++++++++++++++++++ 10 files changed, 128 insertions(+), 41 deletions(-) rename api/{main.go => api.go} (100%) create mode 100644 config.template.yaml create mode 100644 config/config.go delete mode 100644 screen/graph1.go rename screen/{main.go => screen.go} (91%) create mode 100644 screen/tap.go diff --git a/.gitignore b/.gitignore index 3df7a85..6b461d4 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,6 @@ # Go workspace file go.work -tmp.go \ No newline at end of file +tmp.go + +config.yaml diff --git a/api/main.go b/api/api.go similarity index 100% rename from api/main.go rename to api/api.go diff --git a/api/cammie.go b/api/cammie.go index 4f0754d..36871d4 100644 --- a/api/cammie.go +++ b/api/cammie.go @@ -3,6 +3,7 @@ package api import ( "fmt" "net/http" + "scc/config" "scc/screen" "slices" @@ -20,13 +21,13 @@ type cammieHeader struct { IP string `header:"X-Real-IP"` } -var cammieCessages uint64 = 0 -var cammieBlockedNames = []string{"Paul-Henri Spaak"} // Blocked names -var cammieBlockedIps = []string{} // Blocked IPs -var cammieMaxMessageLength = 200 // Maximum message length +var cammieMessages uint64 = 0 +var cammieBlockedNames = config.GetConfig().Cammie.BlockedNames // Blocked names +var cammieBlockedIps = config.GetConfig().Cammie.BlockedIps // Blocked IPs +var cammieMaxMessageLength = config.GetConfig().Cammie.MaxMessageLength // Maximum message length func cammieGetMessage(app *screen.ScreenApp, c *gin.Context) { - c.JSON(200, gin.H{"messages": cammieCessages}) + c.JSON(200, gin.H{"messages": cammieMessages}) } func cammiePostMessage(app *screen.ScreenApp, c *gin.Context) { @@ -71,7 +72,7 @@ func cammiePostMessage(app *screen.ScreenApp, c *gin.Context) { } // Increment messages - cammieCessages++ + cammieMessages++ app.Cammie.Update(newMessage) diff --git a/api/spotify.go b/api/spotify.go index 3691367..4cc1d45 100644 --- a/api/spotify.go +++ b/api/spotify.go @@ -3,9 +3,10 @@ package api import ( "encoding/json" "fmt" + "log" "net/http" "net/url" - "os" + "scc/config" "scc/screen" "strings" "time" @@ -32,10 +33,17 @@ type spotifyTrackResponse struct { Artists []spotifyArtist `json:"artists"` } -var spotifyAccessToken = "" -var spotifyExpiresOn int64 = 0 -var spotifyClientID = "d385173507a54bca93cc3327c0c2f5d9" -var spotifyClientSecret = "8e78977c1ba54b90b17f9dcd6b301c37" +var ( + spotifyAccessToken = "" + spotifyExpiresOn int64 = 0 + spotifyClientID = config.GetConfig().Spotify.ClientID + spotifyClientSecret = config.GetConfig().Spotify.ClientSecret +) + +// var spotifyAccessToken = "" +// var spotifyExpiresOn int64 = 0 +// var spotifyClientID = "d385173507a54bca93cc3327c0c2f5d9" +// var spotifyClientSecret = "8e78977c1ba54b90b17f9dcd6b301c37" func spotifyGetMessage(app *screen.ScreenApp, ctx *gin.Context) { message := &spotifyMessage{} @@ -49,14 +57,14 @@ func spotifyGetMessage(app *screen.ScreenApp, ctx *gin.Context) { if spotifyExpiresOn < time.Now().Unix() { if err := spotifySetAccessToken(); err != nil { - fmt.Fprintf(os.Stderr, "Error: Unable to refresh spotify token: %s", err) + log.Printf("Error: Unable to refresh spotify token: %s\n", err) } } track, err := spotifyGetTrackTitle(message.TrackID) if err != nil { - fmt.Fprintf(os.Stderr, "Error: Unable to get track information: %s", err) + log.Printf("Error: Unable to get track information: %s\n", err) } app.Spotify.Update(track) diff --git a/config.template.yaml b/config.template.yaml new file mode 100644 index 0000000..baf97ac --- /dev/null +++ b/config.template.yaml @@ -0,0 +1,7 @@ +cammie: + blocked_names: [] + blocked_ips: [] + max_message_length: +spotify: + client_id: + client_secret: diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..2a6e5a6 --- /dev/null +++ b/config/config.go @@ -0,0 +1,44 @@ +package config + +import ( + "log" + "os" + "sync" + + "gopkg.in/yaml.v3" +) + +type cammieConfig struct { + BlockedNames []string `yaml:"blocked_names"` + BlockedIps []string `yaml:"blocked_ips"` + MaxMessageLength int `yaml:"max_message_length"` +} + +type spotifyConfig struct { + ClientID string `yaml:"client_id"` + ClientSecret string `yaml:"client_secret"` +} + +type Config struct { + Cammie cammieConfig `yaml:"cammie"` + Spotify spotifyConfig `yaml:"spotify"` +} + +var ( + configInstance *Config + once sync.Once +) + +func GetConfig() *Config { + once.Do(func() { + configInstance = &Config{} + data, err := os.ReadFile("config.yaml") + if err != nil { + log.Fatalf("Failed to read config file: %v", err) + } + if err := yaml.Unmarshal(data, configInstance); err != nil { + log.Fatalf("Failed to unmarshal config: %v", err) + } + }) + return configInstance +} diff --git a/screen/graph1.go b/screen/graph1.go deleted file mode 100644 index 165dfab..0000000 --- a/screen/graph1.go +++ /dev/null @@ -1,23 +0,0 @@ -package screen - -import "github.com/rivo/tview" - -type Graph1 struct { - ScreenApp *ScreenApp - view *tview.Box -} - -func NewGraph1(screenApp *ScreenApp) *Graph1 { - graph1 := Graph1{ - ScreenApp: screenApp, - view: tview.NewBox().SetBorder(true).SetTitle(" Graph 1 "), - } - - return &graph1 -} - -func (graph1 *Graph1) Run() { -} - -func (graph1 *Graph1) Update(text string) { -} diff --git a/screen/main.go b/screen/screen.go similarity index 91% rename from screen/main.go rename to screen/screen.go index 1576501..cb21e61 100644 --- a/screen/main.go +++ b/screen/screen.go @@ -13,7 +13,7 @@ type ScreenApp struct { Spotify *Spotify Cammie *Cammie - Graph1 *Graph1 + Tap *Tap Graph2 *Graph2 } @@ -32,7 +32,7 @@ func NewScreenApp() *ScreenApp { screen.Spotify = NewSpotify(&screen) screen.Cammie = NewCammie(&screen) - screen.Graph1 = NewGraph1(&screen) + screen.Tap = NewTap(&screen) screen.Graph2 = NewGraph2(&screen) // Build the screen layout @@ -41,7 +41,7 @@ func NewScreenApp() *ScreenApp { AddItem(tview.NewFlex(). AddItem(screen.Cammie.view, 0, 5, false). AddItem(tview.NewFlex().SetDirection(tview.FlexRow). - AddItem(screen.Graph1.view, 0, 1, false). + AddItem(screen.Tap.view, 0, 1, false). AddItem(screen.Graph2.view, 0, 1, false), 0, 4, false), 0, 13, false), true). EnableMouse(true) @@ -54,7 +54,7 @@ func Start(screen *ScreenApp) { // Start each screen component go screen.Spotify.Run() go screen.Cammie.Run() - go screen.Graph1.Run() + go screen.Tap.Run() go screen.Graph2.Run() // Start the screen application diff --git a/screen/tap.go b/screen/tap.go new file mode 100644 index 0000000..2176ab5 --- /dev/null +++ b/screen/tap.go @@ -0,0 +1,23 @@ +package screen + +import "github.com/rivo/tview" + +type Tap struct { + ScreenApp *ScreenApp + view *tview.Box +} + +func NewTap(screenApp *ScreenApp) *Tap { + tap := Tap{ + ScreenApp: screenApp, + view: tview.NewBox().SetBorder(true).SetTitle(" Tap "), + } + + return &tap +} + +func (tap *Tap) Run() { +} + +func (tap *Tap) Update(text string) { +} diff --git a/utils/utils.go b/utils/utils.go index db4314a..3f8c5d8 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -2,9 +2,34 @@ package utils import ( "math/rand/v2" + "os" + "strconv" "time" ) +func GetEnv(key, defaultValue string) string { + if value := os.Getenv(key); value != "" { + return value + } + return defaultValue +} + +func GetEnvAsInt(name string, defaultValue int) int { + valueStr := os.Getenv(name) + if value, err := strconv.Atoi(valueStr); err == nil { + return value + } + return defaultValue +} + +func GetEnvAsBool(name string, defaultValue bool) bool { + valueStr := os.Getenv(name) + if value, err := strconv.ParseBool(valueStr); err == nil { + return value + } + return defaultValue +} + func RandRange(min, max int) int { return rand.IntN(max-min) + min } From 3f800383462544013d3c5bb5f74b5ac6288d40c0 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 9 Aug 2024 23:11:24 +0200 Subject: [PATCH 3/3] feat: show soft vs mate chart --- .gitignore | 2 ++ api/api.go | 4 +++ api/cammie.go | 10 +++++--- api/spotify.go | 5 ---- api/tap.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ config/config.go | 7 ++++++ go.mod | 17 +++++++------ go.sum | 43 ++++++++++++++++++++++---------- screen/cammie.go | 14 ++++++----- screen/screen.go | 4 +-- screen/tap.go | 60 ++++++++++++++++++++++++++++++++++++++++++--- 11 files changed, 188 insertions(+), 42 deletions(-) create mode 100644 api/tap.go diff --git a/.gitignore b/.gitignore index 6b461d4..c6baa77 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ go.work tmp.go config.yaml + +scc diff --git a/api/api.go b/api/api.go index cc7eafd..de9d251 100644 --- a/api/api.go +++ b/api/api.go @@ -30,5 +30,9 @@ func Start(screenApp *screen.ScreenApp) { // Spotify routes r.POST("/spotify", handlerWrapper(screenApp, spotifyGetMessage)) + // Start Tap + go runTapRequests(screenApp) + + // Start API r.Run() } diff --git a/api/cammie.go b/api/cammie.go index 36871d4..2e36dc1 100644 --- a/api/cammie.go +++ b/api/cammie.go @@ -21,10 +21,12 @@ type cammieHeader struct { IP string `header:"X-Real-IP"` } -var cammieMessages uint64 = 0 -var cammieBlockedNames = config.GetConfig().Cammie.BlockedNames // Blocked names -var cammieBlockedIps = config.GetConfig().Cammie.BlockedIps // Blocked IPs -var cammieMaxMessageLength = config.GetConfig().Cammie.MaxMessageLength // Maximum message length +var ( + cammieMessages uint64 = 0 + cammieBlockedNames = config.GetConfig().Cammie.BlockedNames // Blocked names + cammieBlockedIps = config.GetConfig().Cammie.BlockedIps // Blocked IPs + cammieMaxMessageLength = config.GetConfig().Cammie.MaxMessageLength // Maximum message length +) func cammieGetMessage(app *screen.ScreenApp, c *gin.Context) { c.JSON(200, gin.H{"messages": cammieMessages}) diff --git a/api/spotify.go b/api/spotify.go index 4cc1d45..5b1b47a 100644 --- a/api/spotify.go +++ b/api/spotify.go @@ -40,11 +40,6 @@ var ( spotifyClientSecret = config.GetConfig().Spotify.ClientSecret ) -// var spotifyAccessToken = "" -// var spotifyExpiresOn int64 = 0 -// var spotifyClientID = "d385173507a54bca93cc3327c0c2f5d9" -// var spotifyClientSecret = "8e78977c1ba54b90b17f9dcd6b301c37" - func spotifyGetMessage(app *screen.ScreenApp, ctx *gin.Context) { message := &spotifyMessage{} diff --git a/api/tap.go b/api/tap.go new file mode 100644 index 0000000..da9f1ac --- /dev/null +++ b/api/tap.go @@ -0,0 +1,64 @@ +package api + +import ( + "encoding/json" + "log" + "net/http" + "scc/config" + "scc/screen" + "time" +) + +type tapReponse struct { + Orders []screen.TapOrder `json:"orders"` +} + +var ( + tapURL = config.GetConfig().Tap.URL + timestampLayout = config.GetConfig().Tap.TimestampLayout + lastOrderTimestamp = time.Time{} +) + +func runTapRequests(app *screen.ScreenApp) { + for true { + recentOrders, err := tapGetRecentOrders() + if err != nil { + log.Printf("Error: Unable to get recent order: %s\n", err) + } + for _, order := range recentOrders.Orders { + timestamp, err := time.Parse(timestampLayout, order.OrderCreatedAt) + if err != nil { + log.Printf("Error: Unable to parse timestamp: %s\n", err) + } + + if order.ProductCategory == "beverages" && timestamp.After(lastOrderTimestamp) { + app.Tap.Update(&order) + lastOrderTimestamp = timestamp + } + } + + time.Sleep(1 * time.Minute) + } +} + +func tapGetRecentOrders() (*tapReponse, error) { + req, err := http.NewRequest("GET", tapURL, nil) + if err != nil { + return nil, err + } + req.Header.Set("Accept", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + response := &tapReponse{} + if err := json.NewDecoder(resp.Body).Decode(response); err != nil { + return nil, err + } + + return response, nil +} diff --git a/config/config.go b/config/config.go index 2a6e5a6..60bc888 100644 --- a/config/config.go +++ b/config/config.go @@ -19,9 +19,16 @@ type spotifyConfig struct { ClientSecret string `yaml:"client_secret"` } +type tapConfig struct { + URL string `yaml:"url"` + TimestampLayout string `yaml:"timestamp_layout"` + Beers []string `yaml:"beer"` +} + type Config struct { Cammie cammieConfig `yaml:"cammie"` Spotify spotifyConfig `yaml:"spotify"` + Tap tapConfig `yaml:"tap"` } var ( diff --git a/go.mod b/go.mod index 26a2f7f..36ba5ce 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,10 @@ module scc go 1.22.0 require ( - github.com/gdamore/tcell/v2 v2.7.1 + github.com/gdamore/tcell/v2 v2.7.4 github.com/gin-gonic/gin v1.9.1 - github.com/rivo/tview v0.0.0-20240225120200-5605142ca62e + github.com/rivo/tview v0.0.0-20240616192244-23476fa0bab2 + gopkg.in/yaml.v3 v3.0.1 ) require ( @@ -26,16 +27,16 @@ require ( github.com/mattn/go-runewidth v0.0.15 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/navidys/tvxwidgets v0.7.0 github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/term v0.17.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/term v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 47fe4b6..0d31f70 100644 --- a/go.sum +++ b/go.sum @@ -11,12 +11,14 @@ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell/v2 v2.7.1 h1:TiCcmpWHiAU7F0rA2I3S2Y4mmLmO9KHxJ7E1QhYzQbc= -github.com/gdamore/tcell/v2 v2.7.1/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= +github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU= +github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -25,12 +27,17 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -49,12 +56,18 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/navidys/tvxwidgets v0.7.0 h1:ls5tikzqXnsHwAAV/8zwnRwx/DvSybepUih9txkwjwE= +github.com/navidys/tvxwidgets v0.7.0/go.mod h1:hzFnllDl4o2Ten/67T0F8ZgC1NiLrZYqWxLVjxWu+zo= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/tview v0.0.0-20240225120200-5605142ca62e h1:7ubTieBkl4KCz5ABZzh0zPkBYWPguSOHUundUsorIzQ= -github.com/rivo/tview v0.0.0-20240225120200-5605142ca62e/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss= +github.com/rivo/tview v0.0.0-20240616192244-23476fa0bab2 h1:LXMiBMxtuXw8e2paN61dI2LMp8JZYyH4UXDwssRI3ys= +github.com/rivo/tview v0.0.0-20240616192244-23476fa0bab2/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= @@ -80,16 +93,16 @@ golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= 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= @@ -101,25 +114,29 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= diff --git a/screen/cammie.go b/screen/cammie.go index 83c962d..015c794 100644 --- a/screen/cammie.go +++ b/screen/cammie.go @@ -41,13 +41,16 @@ type Cammie struct { func NewCammie(screenApp *ScreenApp) *Cammie { cammie := Cammie{ screenApp: screenApp, - view: tview.NewTextView().SetWordWrap(true).SetScrollable(true).SetDynamicColors(true), + view: tview.NewTextView(). + SetWordWrap(true). + SetScrollable(true). + SetDynamicColors(true), } - cammie.view.SetTitle(" Cammie ") - cammie.view.SetBorder(true) - cammie.view.SetBorderColor(tcell.ColorOrange) - cammie.view.SetTitleColor(tcell.ColorOrange) + cammie.view.SetTitle(" Cammie "). + SetBorder(true). + SetBorderColor(tcell.ColorOrange). + SetTitleColor(tcell.ColorOrange) return &cammie } @@ -56,7 +59,6 @@ func NewCammie(screenApp *ScreenApp) *Cammie { func (cammie *Cammie) Run() { // Wait for the view to be properly set up time.Sleep(1 * time.Second) - } // Updates the cammie chat diff --git a/screen/screen.go b/screen/screen.go index cb21e61..7c51300 100644 --- a/screen/screen.go +++ b/screen/screen.go @@ -13,7 +13,7 @@ type ScreenApp struct { Spotify *Spotify Cammie *Cammie - Tap *Tap + Tap *Tap Graph2 *Graph2 } @@ -40,7 +40,7 @@ func NewScreenApp() *ScreenApp { AddItem(screen.Spotify.view, 3, 2, false). AddItem(tview.NewFlex(). AddItem(screen.Cammie.view, 0, 5, false). - AddItem(tview.NewFlex().SetDirection(tview.FlexRow). + AddItem(tview.NewFlex().SetDirection(tview.FlexColumn). AddItem(screen.Tap.view, 0, 1, false). AddItem(screen.Graph2.view, 0, 1, false), 0, 4, false), 0, 13, false), true). EnableMouse(true) diff --git a/screen/tap.go b/screen/tap.go index 2176ab5..e26dd38 100644 --- a/screen/tap.go +++ b/screen/tap.go @@ -1,23 +1,75 @@ package screen -import "github.com/rivo/tview" +import ( + "scc/config" + "strings" + + "github.com/gdamore/tcell/v2" + "github.com/navidys/tvxwidgets" + "github.com/rivo/tview" +) + +type TapOrder struct { + OrderID int `json:"order_id"` + OrderCreatedAt string `json:"order_created_at"` + ProductName string `json:"product_name"` + ProductCategory string `json:"product_category"` +} type Tap struct { ScreenApp *ScreenApp - view *tview.Box + view *tview.Flex + bar *tvxwidgets.BarChart } +var ( + soft = 0 + mate = 0 + beer = 0 +) + func NewTap(screenApp *ScreenApp) *Tap { tap := Tap{ ScreenApp: screenApp, - view: tview.NewBox().SetBorder(true).SetTitle(" Tap "), + view: tview.NewFlex(), + bar: tvxwidgets.NewBarChart(), } + tap.view.SetBorder(true).SetTitle(" Tap ") + + tap.bar.AddBar("Soft", 0, tcell.ColorBlue) + tap.bar.AddBar("Mate", 0, tcell.ColorOrange) + tap.bar.AddBar("Beer", 0, tcell.ColorRed) + tap.bar.SetAxesLabelColor(tcell.ColorWhite) + + tap.view.AddItem(tap.bar, 0, 1, true) + return &tap } func (tap *Tap) Run() { } -func (tap *Tap) Update(text string) { +func (tap *Tap) Update(order *TapOrder) { + switch { + case strings.Contains(order.ProductName, "Mate"): + mate++ + tap.bar.SetBarValue("Mate", mate) + case isBeer(order.ProductName): + beer++ + tap.bar.SetBarValue("Beer", beer) + default: + soft++ + tap.bar.SetBarValue("Soft", soft) + } +} + +func isBeer(productName string) bool { + for _, beer := range config.GetConfig().Tap.Beers { + if strings.Contains(productName, beer) { + return true + } + } + + return false }