checkpoint: add configuration

This commit is contained in:
Dan Anglin 2024-06-24 09:01:28 +01:00
parent 63f0526f39
commit bb71d2988c
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
6 changed files with 138 additions and 35 deletions

View file

@ -10,6 +10,7 @@ import (
"os"
"strconv"
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
"codeflow.dananglin.me.uk/apollo/enbas/internal/executor"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
)
@ -29,22 +30,11 @@ func main() {
func run() error {
var (
configDir string
cacheDir string
pager string
imageViewer string
videoPlayer string
maxTerminalWidth int
noColor *bool
configDir string
noColor *bool
)
flag.StringVar(&configDir, "config-dir", "", "Specify your config directory")
flag.StringVar(&cacheDir, "cache-dir", "", "Specify your cache directory")
flag.StringVar(&pager, "pager", "", "Specify your preferred pager to page through long outputs. This is disabled by default.")
flag.StringVar(&imageViewer, "image-viewer", "", "Specify your favourite image viewer.")
flag.StringVar(&videoPlayer, "video-player", "", "Specify your favourite video player.")
flag.IntVar(&maxTerminalWidth, "max-terminal-width", 80, "Specify the maximum terminal width when displaying resources on screen.")
flag.BoolFunc("no-color", "Disable ANSI colour output when displaying text on screen", func(value string) error {
boolVal, err := strconv.ParseBool(value)
if err != nil {
@ -80,7 +70,15 @@ func run() error {
command := flag.Arg(0)
args := flag.Args()[1:]
printer := printer.NewPrinter(*noColor, pager, maxTerminalWidth)
config, err := config.NewConfigFromFile(configDir)
if err != nil {
printer := printer.NewPrinter(*noColor, "", 80)
printer.PrintFailure("unable to load the configuration: " + err.Error() + ".")
return err
}
printer := printer.NewPrinter(*noColor, config.Integrations.Pager, config.LineWrapMaxWidth)
executorMap := map[string]executor.Executor{
executor.CommandAccept: executor.NewAcceptOrRejectExecutor(
@ -175,10 +173,8 @@ func run() error {
),
executor.CommandShow: executor.NewShowExecutor(
printer,
&config,
configDir,
cacheDir,
imageViewer,
videoPlayer,
executor.CommandShow,
executor.CommandSummaryLookup(executor.CommandShow),
),

103
internal/config/config.go Normal file
View file

@ -0,0 +1,103 @@
package config
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
)
const (
configFileName = "config.json"
)
type Config struct {
CacheDirectory string `json:"cacheDirectory"`
LineWrapMaxWidth int `json:"lineWrapMaxWidth"`
HTTP HTTPConfig `json:"http"`
Integrations Integrations `json:"integrations"`
}
type HTTPConfig struct {
Timeout int `json:"timeout"`
MediaTimeout int `json:"mediaTimeout"`
}
type Integrations struct {
Browser string `json:"browser"`
Editor string `json:"editor"`
Pager string `json:"pager"`
ImageViewer string `json:"imageViewer"`
VideoPlayer string `json:"videoPlayer"`
}
func NewConfigFromFile(configDir string) (Config, error) {
path := configFile(configDir)
fileExists, err := utilities.FileExists(path)
if err != nil {
return Config{}, fmt.Errorf("unable to check if the config file exists: %w", err)
}
if !fileExists {
if err := saveDefaultConfigToFile(path); err != nil {
return Config{}, fmt.Errorf("unable to save the default config to file: %w", err)
}
}
file, err := os.Open(path)
if err != nil {
return Config{}, fmt.Errorf("unable to open %s: %w", path, err)
}
defer file.Close()
var config Config
if err := json.NewDecoder(file).Decode(&config); err != nil {
return Config{}, fmt.Errorf("unable to decode the JSON data: %w", err)
}
return config, nil
}
func configFile(configDir string) string {
return filepath.Join(utilities.CalculateConfigDir(configDir), configFileName)
}
func saveDefaultConfigToFile(path string) error {
file, err := os.Create(path)
if err != nil {
return fmt.Errorf("unable to create the file at %s: %w", path, err)
}
defer file.Close()
config := defaultConfig()
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ")
if err := encoder.Encode(config); err != nil {
return fmt.Errorf("unable to save the JSON data to the config file: %w", err)
}
return nil
}
func defaultConfig() Config {
return Config{
CacheDirectory: "",
HTTP: HTTPConfig{
Timeout: 5,
MediaTimeout: 30,
},
LineWrapMaxWidth: 80,
Integrations: Integrations{
Browser: "",
Editor: "",
Pager: "",
ImageViewer: "",
VideoPlayer: "",
},
}
}

View file

@ -109,7 +109,7 @@ func NewCredentialsConfigFromFile(configDir string) (CredentialsConfig, error) {
file, err := os.Open(path)
if err != nil {
return CredentialsConfig{}, fmt.Errorf("unable to open %s, %w", path, err)
return CredentialsConfig{}, fmt.Errorf("unable to open %s: %w", path, err)
}
defer file.Close()
@ -127,9 +127,8 @@ func saveCredentialsConfigFile(authConfig CredentialsConfig, configDir string) e
file, err := os.Create(path)
if err != nil {
return fmt.Errorf("unable to open %s: %w", path, err)
return fmt.Errorf("unable to create the file at %s: %w", path, err)
}
defer file.Close()
encoder := json.NewEncoder(file)

View file

@ -102,3 +102,11 @@ type NotFollowingError struct {
func (e NotFollowingError) Error() string {
return "you are not following " + e.Account
}
type UnknownMediaAttachmentError struct {
AttachmentID string
}
func (e UnknownMediaAttachmentError) Error() string {
return "unknown media attachment '" + e.AttachmentID + "'"
}

View file

@ -11,6 +11,7 @@ import (
"strings"
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
@ -20,12 +21,12 @@ type ShowExecutor struct {
*flag.FlagSet
printer *printer.Printer
config *config.Config
myAccount bool
skipAccountRelationship bool
showUserPreferences bool
showInBrowser bool
configDir string
cacheRoot string
resourceType string
accountName string
statusID string
@ -34,21 +35,17 @@ type ShowExecutor struct {
tag string
pollID string
fromResourceType string
imageViewer string
videoPlayer string
limit int
attachmentIDs MultiStringFlagValue
}
func NewShowExecutor(printer *printer.Printer, configDir, cacheRoot, imageViewer, videoPlayer, name, summary string) *ShowExecutor {
func NewShowExecutor(printer *printer.Printer, config *config.Config, configDir, name, summary string) *ShowExecutor {
showExe := ShowExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
printer: printer,
configDir: configDir,
cacheRoot: cacheRoot,
imageViewer: imageViewer,
videoPlayer: videoPlayer,
printer: printer,
config: config,
configDir: configDir,
}
showExe.BoolVar(&showExe.myAccount, flagMyAccount, false, "Set to true to lookup your account")
@ -471,7 +468,7 @@ func (s *ShowExecutor) showMediaFromStatus(gtsClient *client.Client) error {
}
cacheDir := filepath.Join(
utilities.CalculateCacheDir(s.cacheRoot, utilities.GetFQDN(gtsClient.Authentication.Instance)),
utilities.CalculateCacheDir(s.config.CacheDirectory, utilities.GetFQDN(gtsClient.Authentication.Instance)),
"media",
)
@ -498,7 +495,7 @@ func (s *ShowExecutor) showMediaFromStatus(gtsClient *client.Client) error {
for _, attachmentID := range s.attachmentIDs {
mediaObj, ok := attachmentsHashMap[attachmentID]
if !ok {
return fmt.Errorf("unknown media attachment: %s", attachmentID)
return UnknownMediaAttachmentError{AttachmentID: attachmentID}
}
split := strings.Split(mediaObj.url, "/")
@ -533,13 +530,13 @@ func (s *ShowExecutor) showMediaFromStatus(gtsClient *client.Client) error {
}
if len(imageFiles) > 0 {
if err := utilities.OpenMedia(s.imageViewer, imageFiles); err != nil {
if err := utilities.OpenMedia(s.config.Integrations.ImageViewer, imageFiles); err != nil {
return fmt.Errorf("unable to open the image viewer: %w", err)
}
}
if len(videoFiles) > 0 {
if err := utilities.OpenMedia(s.videoPlayer, videoFiles); err != nil {
if err := utilities.OpenMedia(s.config.Integrations.VideoPlayer, videoFiles); err != nil {
return fmt.Errorf("unable to open the video player: %w", err)
}
}

View file

@ -20,7 +20,7 @@ func CalculateConfigDir(configDir string) string {
configRoot, err := os.UserConfigDir()
if err != nil {
configRoot = "."
return filepath.Join(os.Getenv("HOME"), "."+internal.ApplicationName, "config")
}
return filepath.Join(configRoot, internal.ApplicationName)
@ -33,7 +33,7 @@ func CalculateCacheDir(cacheDir, instanceFQDN string) string {
cacheRoot, err := os.UserCacheDir()
if err != nil {
cacheRoot = "."
return filepath.Join(os.Getenv("HOME"), "."+internal.ApplicationName, "cache")
}
return filepath.Join(cacheRoot, internal.ApplicationName, instanceFQDN)