jirashell/main.go

170 lines
3.4 KiB
Go

package main
import (
"github.com/abiosoft/ishell/v2"
"github.com/adrg/xdg"
"github.com/andygrunwald/go-jira"
prompt "github.com/elk-language/go-prompt"
pstrings "github.com/elk-language/go-prompt/strings"
"github.com/pkg/errors"
"github.com/spf13/viper"
"log"
"os"
)
var configPath string
var shell *ishell.Shell
var jiraClient *jira.Client
var promptRunner *prompt.Prompt
var prefix = "> "
func loadConfig() {
err := viper.ReadInConfig()
if err != nil {
log.Fatal(err)
}
}
func SaveConfig() {
err := viper.WriteConfig()
if err != nil {
log.Fatal(err)
}
}
func GetProjectId() string {
return viper.GetString("project.id")
}
func GetSprintId() int {
return viper.GetInt("sprint.id")
}
func UpdatePrompt() {
prefix = ""
if HasProject() {
prefix = prefix + "p:" + viper.GetString("project.key") + " "
}
if HasBoard() {
prefix = prefix + "b:" + viper.GetString("board.name") + " "
}
if HasSprint() {
prefix = prefix + "s:" + viper.GetString("sprint.name") + " "
}
if len(prefix) > 0 {
prefix = prefix[0:len(prefix)-1] + "> "
} else {
prefix = "> "
}
}
func executor(in string) {
command, args := GetCommand(in)
if command == nil {
println("Invalid command", in)
return
}
command.Action(args)
}
func completer(d prompt.Document) ([]prompt.Suggest, pstrings.RuneNumber, pstrings.RuneNumber) {
endIndex := d.CurrentRuneIndex()
w := d.GetWordBeforeCursor()
startIndex := endIndex - pstrings.RuneCount([]byte(w))
s := GetSuggestionsFor(d.TextBeforeCursor())
return prompt.FilterHasPrefix(s, w, true), startIndex, endIndex
}
func main() {
// Open config file
configPath, err := xdg.ConfigFile("jirashell/config.toml")
if err != nil {
log.Fatal(err)
}
viper.SetConfigFile(configPath)
_, err = os.Stat(configPath)
if err != nil && !errors.Is(err, os.ErrNotExist) {
log.Fatal(err)
} else if err == nil {
loadConfig()
}
ensureLoggedIn()
UpdatePrompt()
promptRunner = prompt.New(
executor,
prompt.WithCompleter(completer),
prompt.WithTitle("jirashell"),
prompt.WithPrefixCallback(func() string { return prefix }),
)
promptRunner.Run()
}
func ensureLoggedIn() {
for {
username := viper.GetString("username")
host := viper.GetString("host")
token := viper.GetString("token")
if host != "" && token != "" && username != "" {
println("Logging in...")
err := login(host, username, token)
if err != nil {
println("Could not log in:", err)
} else {
println("Logged in!")
SaveConfig()
return
}
}
println()
println("A host name is required.")
host = prompt.Input(prompt.WithPrefix("Host: "), prompt.WithInitialText(host))
if host == "" {
return
}
viper.Set("host", host)
println()
println("A username is required.")
username = prompt.Input(prompt.WithPrefix("Username: "), prompt.WithInitialText(username))
if username == "" {
return
}
viper.Set("username", username)
println()
println("A token is required.")
token = prompt.Input(prompt.WithPrefix("Token: "), prompt.WithInitialText(token))
if token == "" {
return
}
viper.Set("token", token)
}
}
func login(host, username, token string) error {
var err error
tp := jira.BasicAuthTransport{
Username: username,
Password: token,
}
jiraClient, err = jira.NewClient(tp.Client(), host)
if err != nil {
return err
}
_, _, err = jiraClient.User.GetSelf()
if err != nil {
return err
}
return nil
}
func noSuggestions(doc prompt.Document) []prompt.Suggest {
return make([]prompt.Suggest, 0)
}