馃尫 the cutsie hackatime helper
1package handler 2 3import ( 4 "errors" 5 "fmt" 6 "os" 7 "runtime" 8 "strings" 9 10 "github.com/spf13/cobra" 11 "github.com/taciturnaxolotl/akami/styles" 12 "github.com/taciturnaxolotl/akami/wakatime" 13 "gopkg.in/ini.v1" 14) 15 16func Doctor() *cobra.Command { 17 return &cobra.Command{ 18 Use: "doc", 19 Short: "diagnose potential hackatime issues", 20 RunE: func(c *cobra.Command, _ []string) error { 21 // check our os 22 os_name := runtime.GOOS 23 24 user_dir, err := os.UserHomeDir() 25 if err != nil { 26 return errors.New("somehow your user doesn't exist? fairly sure this should never happen; plz report this to @krn on slack or via email at me@dunkirk.sh") 27 } 28 hackatime_path := user_dir + "/.wakatime.cfg" 29 30 switch os_name { 31 case "linux": 32 case "darwin": 33 case "windows": 34 default: 35 return errors.New("hmm you don't seem to be running a recognized os? you are listed as running " + styles.Fancy.Render(os_name) + "; can you plz report this to @krn on slack or via email at me@dunkirk.sh?") 36 } 37 38 c.Println("Looks like you are running", styles.Fancy.Render(os_name), "so lets take a look at", styles.Muted.Render(hackatime_path), "for your config") 39 40 rawCfg, err := os.ReadFile(hackatime_path) 41 if errors.Is(err, os.ErrNotExist) { 42 return errors.New("you don't have a wakatime config file! go check https://hackatime.hackclub.com/my/wakatime_setup for the instructions and then try this again") 43 } 44 45 cfg, err := ini.Load(rawCfg) 46 if err != nil { 47 return errors.New(err.Error()) 48 } 49 50 settings, err := cfg.GetSection("settings") 51 if err != nil { 52 return errors.New("wow! your config file seems to be messed up and doesn't have a settings heading; can you follow the instructions at https://hackatime.hackclub.com/my/wakatime_setup to regenerate it?\n\nThe raw error we got was: " + err.Error()) 53 } 54 55 api_key := settings.Key("api_key").String() 56 api_url := settings.Key("api_url").String() 57 if api_key == "" { 58 return errors.New("hmm 馃 looks like you don't have an api_key in your config file? are you sure you have followed the setup instructions at https://hackatime.hackclub.com/my/wakatime_setup correctly?") 59 } 60 if api_url == "" { 61 return errors.New("hmm 馃 looks like you don't have an api_url in your config file? are you sure you have followed the setup instructions at https://hackatime.hackclub.com/my/wakatime_setup correctly?") 62 } 63 64 if api_url != "https://hackatime.hackclub.com/api/hackatime/v1" { 65 if api_url == "https://api.wakatime.com/api/v1" { 66 client := wakatime.NewClient(api_key) 67 _, err := client.GetStatusBar() 68 69 if !errors.Is(err, wakatime.ErrUnauthorized) { 70 return errors.New("turns out you were connected to wakatime.com instead of hackatime; since your key seems to work if you would like to keep syncing data to wakatime.com as well as to hackatime you can either setup a realy serve like " + styles.Muted.Render("https://github.com/JasonLovesDoggo/multitime") + " or you can wait for https://github.com/hackclub/hackatime/issues/85 to get merged in hackatime and have it synced there :)\n\nIf you want to import your wakatime.com data into hackatime then you can use hackatime v1 temporarily to connect your wakatime account and import (in settings under integrations at https://waka.hackclub.com) and then click the import from hackatime v1 button at https://hackatime.hackclub.com/my/settings.\n\n If you have more questions feel free to reach out to me (hackatime v1 creator) on slack (at @krn) or via email at me@dunkirk.sh") 71 } else { 72 return errors.New("turns out your config is connected to the wrong api url and is trying to use wakatime.com to sync time but you don't have a working api key from them. Go to https://hackatime.hackclub.com/my/wakatime_setup to run the setup script and fix your config file") 73 } 74 } 75 c.Println("\nYour api url", styles.Muted.Render(api_url), "doesn't match the expected url of", styles.Muted.Render("https://hackatime.hackclub.com/api/hackatime/v1"), "however if you are using a custom forwarder or are sure you know what you are doing then you are probably fine") 76 } 77 78 client := wakatime.NewClientWithOptions(api_key, api_url) 79 duration, err := client.GetStatusBar() 80 if err != nil { 81 if errors.Is(err, wakatime.ErrUnauthorized) { 82 return errors.New("Your config file looks mostly correct and you have the correct api url but when we tested your api_key it looks like it is invalid? Can you double check if the key in your config file is the same as at https://hackatime.hackclub.com/my/wakatime_setup?") 83 } 84 85 return errors.New("Something weird happened with the hackatime api; if the error doesn't make sense then please contact @krn on slack or via email at me@dunkirk.sh\n\n" + styles.Bad.Render("Full error: "+err.Error())) 86 } 87 88 // Convert seconds to a formatted time string (hours, minutes, seconds) 89 totalSeconds := duration.Data.GrandTotal.TotalSeconds 90 hours := totalSeconds / 3600 91 minutes := (totalSeconds % 3600) / 60 92 seconds := totalSeconds % 60 93 94 formattedTime := "" 95 if hours > 0 { 96 formattedTime += fmt.Sprintf("%d hours, ", hours) 97 } 98 if minutes > 0 || hours > 0 { 99 formattedTime += fmt.Sprintf("%d minutes, ", minutes) 100 } 101 formattedTime += fmt.Sprintf("%d seconds", seconds) 102 103 c.Println("\nSweet!!! Looks like your hackatime is configured properly! Looks like you have coded today for", styles.Fancy.Render(formattedTime)) 104 105 c.Println("\nSending one quick heartbeat to make sure everything is ship shape and then you should be good to go!") 106 107 err = client.SendHeartbeat(wakatime.Heartbeat{ 108 Entity: "/home/kierank/Projects/akami/wakatime/main.go", 109 Type: "file", 110 Project: "akami", 111 Language: "Go", 112 Branch: "main", 113 Category: "coding", 114 IsWrite: true, 115 LineCount: 197, 116 ProjectRootCount: 5, 117 Dependencies: []string{"bytes", "encoding/base64", "encoding/json", "net/http", "runtime", "time"}, 118 Time: 1750643351, 119 }) 120 if err != nil { 121 return errors.New("oh dear; looks like something went wrong when sending that heartbeat. " + styles.Bad.Render("Full error: \""+strings.TrimSpace(err.Error())+"\"")) 122 } 123 124 c.Println("\n馃コ it worked! you are good to go! Happy coding 馃憢") 125 126 return nil 127 }, 128 } 129 130}