🌷 the cutsie hackatime helper
1package main 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "os" 8 "runtime" 9 10 "github.com/charmbracelet/fang" 11 "github.com/charmbracelet/lipgloss/v2" 12 "github.com/spf13/cobra" 13 "github.com/taciturnaxolotl/akami/wakatime" 14 "gopkg.in/ini.v1" 15) 16 17func main() { 18 // init our cobra command with a name and description 19 cmd := &cobra.Command{ 20 Use: "akami", 21 Short: "🌷 the cutsie hackatime helper", 22 } 23 24 // add our lipgloss styles 25 fancy := lipgloss.NewStyle().Foreground(lipgloss.Magenta).Bold(true).Italic(true) 26 muted := lipgloss.NewStyle().Foreground(lipgloss.BrightBlue).Italic(true) 27 bad := lipgloss.NewStyle().Foreground(lipgloss.BrightRed).Bold(true) 28 29 // root diagnose command 30 cmd.AddCommand(&cobra.Command{ 31 Use: "doc", 32 Short: "diagnose potential hackatime issues", 33 RunE: func(c *cobra.Command, _ []string) error { 34 // check our os 35 os_name := runtime.GOOS 36 37 user_dir, err := os.UserHomeDir() 38 if err != nil { 39 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") 40 } 41 hackatime_path := user_dir + "/.wakatime.cfg" 42 43 switch os_name { 44 case "linux": 45 case "darwin": 46 case "windows": 47 default: 48 return errors.New("hmm you don't seem to be running a recognized os? you are listed as running " + fancy.Render(os_name) + "; can you plz report this to @krn on slack or via email at me@dunkirk.sh?") 49 } 50 51 c.Println("Looks like you are running", fancy.Render(os_name), "so lets take a look at", muted.Render(hackatime_path), "for your config") 52 53 rawCfg, err := os.ReadFile(hackatime_path) 54 if errors.Is(err, os.ErrNotExist) { 55 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") 56 } 57 58 cfg, err := ini.Load(rawCfg) 59 if err != nil { 60 return errors.New(err.Error()) 61 } 62 63 settings, err := cfg.GetSection("settings") 64 if err != nil { 65 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()) 66 } 67 68 api_key := settings.Key("api_key").String() 69 api_url := settings.Key("api_url").String() 70 if api_key == "" { 71 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?") 72 } 73 if api_url == "" { 74 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?") 75 } 76 77 if api_url != "https://hackatime.hackclub.com/api/hackatime/v1" { 78 if api_url == "https://api.wakatime.com/api/v1" { 79 client := wakatime.NewClient(api_key) 80 _, err := client.GetStatusBar() 81 82 if !errors.Is(err, wakatime.ErrUnauthorized) { 83 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 " + 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") 84 } else { 85 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") 86 } 87 } 88 c.Println("\nYour api url", muted.Render(api_url), "doesn't match the expected url of", 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") 89 } 90 91 client := wakatime.NewClientWithOptions(api_key, api_url) 92 duration, err := client.GetStatusBar() 93 if err != nil { 94 if errors.Is(err, wakatime.ErrUnauthorized) { 95 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?") 96 } 97 98 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" + bad.Render("Full error: "+err.Error())) 99 } 100 101 // Convert seconds to a formatted time string (hours, minutes, seconds) 102 totalSeconds := duration.Data.GrandTotal.TotalSeconds 103 hours := totalSeconds / 3600 104 minutes := (totalSeconds % 3600) / 60 105 seconds := totalSeconds % 60 106 107 formattedTime := "" 108 if hours > 0 { 109 formattedTime += fmt.Sprintf("%d hours, ", hours) 110 } 111 if minutes > 0 || hours > 0 { 112 formattedTime += fmt.Sprintf("%d minutes, ", minutes) 113 } 114 formattedTime += fmt.Sprintf("%d seconds", seconds) 115 116 c.Println("\nSweet!!! Looks like your hackatime is configured properly! Looks like you have coded today for", fancy.Render(formattedTime)) 117 118 return nil 119 }, 120 }) 121 122 // this is where we get the fancy fang magic ✨ 123 if err := fang.Execute( 124 context.Background(), 125 cmd, 126 ); err != nil { 127 os.Exit(1) 128 } 129}