statusbar-go/module_toggl.go

141 lines
3.1 KiB
Go

package main
import (
"encoding/base64"
"encoding/json"
"fmt"
"html"
"io/ioutil"
"net/http"
"os"
"strings"
"time"
)
type togglCurrentResponse struct {
WorkspaceID int `json:"workspace_id"`
ProjectID int `json:"project_id"`
Start string `json:"start"`
}
type togglProjectResponse struct {
Name string `json:"name"`
}
const (
TOGGL_CURRENT_URI = "https://api.track.toggl.com/api/v9/me/time_entries/current"
TOGGL_PROJECT_URI = "https://api.track.toggl.com/api/v9/workspaces/%d/projects/%d"
TOGGL_API_KEY_VAR = "TOGGL_API_TOKEN"
TOGGL_API_KEY_FILE = ".config/toggl-api-token"
)
var TOGGL_API_TOKEN = ""
func load_toggl_api_key() (string, error) {
token := os.Getenv(TOGGL_API_TOKEN)
if token != "" {
return token, nil
}
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
key, err := ioutil.ReadFile(home + "/" + TOGGL_API_KEY_FILE)
if err != nil {
return "", err
}
return strings.ReplaceAll(string(key), "\n", ""), nil
}
func toggl_basic_auth() string {
auth := TOGGL_API_TOKEN + ":api_token"
return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
}
func get_current_toggl_project() string {
if TOGGL_API_TOKEN == "" {
token, err := load_toggl_api_key()
if err != nil {
return "toggl token error"
}
TOGGL_API_TOKEN = token
}
client := &http.Client{}
currentRequest, err := http.NewRequest("GET", TOGGL_CURRENT_URI, nil)
if err != nil {
return "toggl create currentRequest error"
}
currentRequest.Header.Add("Authorization", toggl_basic_auth())
resp, err := client.Do(currentRequest)
if err != nil {
return "toggl currentRequest error"
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "toggl currentRequest body error"
}
if string(body) == "null" {
return "<span foreground=\"white\" background=\"red\"> TOGGL NOT TRACKING </span>"
}
var currentJson togglCurrentResponse
err = json.Unmarshal(body, &currentJson)
if err != nil {
return "toggl currentResponse unmarshal error"
}
if currentJson.ProjectID == 0 {
return get_toggl_time_elapsed(currentJson.Start)
}
projectRequest, err := http.NewRequest("GET", fmt.Sprintf(TOGGL_PROJECT_URI, currentJson.WorkspaceID, currentJson.ProjectID), nil)
if err != nil {
return "toggl create projectRequest error"
}
projectRequest.Header.Add("Authorization", toggl_basic_auth())
resp, err = client.Do(projectRequest)
if err != nil {
return "toggl projectRequest error"
}
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
return "toggl projectRequest body error"
}
var projectJson togglProjectResponse
err = json.Unmarshal(body, &projectJson)
if err != nil {
return "toggl projectResponse unmarshal error"
}
return fmt.Sprintf("%s - %s", html.EscapeString(projectJson.Name), get_toggl_time_elapsed(currentJson.Start))
}
func get_toggl_time_elapsed(start string) string {
t, err := time.Parse(time.RFC3339, start)
if err != nil {
return ""
}
elapsed := time.Since(t)
hours := int(elapsed.Hours())
minutes := int(elapsed.Minutes()) % 60
if hours == 0 {
return fmt.Sprintf("%d min", minutes)
}
return fmt.Sprintf("%d h %d min", hours, minutes)
}