diff --git a/cmd/enbas-cli-generators/main.go b/cmd/enbas-cli-generators/main.go index 0eef6ff..35f39f4 100644 --- a/cmd/enbas-cli-generators/main.go +++ b/cmd/enbas-cli-generators/main.go @@ -36,10 +36,10 @@ func main() { func generateExecutors(schema enbasCLISchema, output string) error { funcMap := template.FuncMap{ - "capitalise": capitalise, - "convertFlagToMixedCaps": convertFlagToMixedCaps, - "getFlagType": schema.Flags.getType, - "getFlagDescription": schema.Flags.getDescription, + "capitalise": capitalise, + "flagFieldName": flagFieldName, + "getFlagType": schema.Flags.getType, + "getFlagDescription": schema.Flags.getDescription, } tmpl := template.Must(template.New("executor-template").Funcs(funcMap).Parse(executorsFileTemplate)) @@ -75,6 +75,14 @@ func capitalise(str string) string { return string(runes) } +func flagFieldName(flagRef enbasCLISchemaFlagReference) string { + if flagRef.FieldName != "" { + return flagRef.FieldName + } + + return convertFlagToMixedCaps(flagRef.Flag) +} + func convertFlagToMixedCaps(value string) string { var builder strings.Builder diff --git a/cmd/enbas-cli-generators/schema.go b/cmd/enbas-cli-generators/schema.go index eb288e5..3a71559 100644 --- a/cmd/enbas-cli-generators/schema.go +++ b/cmd/enbas-cli-generators/schema.go @@ -61,8 +61,9 @@ type enbasCLISchemaCommand struct { } type enbasCLISchemaFlagReference struct { - Flag string `json:"flag"` - Default string `json:"default"` + Flag string `json:"flag"` + FieldName string `json:"fieldName"` + Default string `json:"default"` } type enbasCLISchemaAdditionalFields struct { diff --git a/cmd/enbas-cli-generators/templates.go b/cmd/enbas-cli-generators/templates.go index 162efc0..71d99e4 100644 --- a/cmd/enbas-cli-generators/templates.go +++ b/cmd/enbas-cli-generators/templates.go @@ -1,6 +1,11 @@ package main var executorsFileTemplate = `package executor +{{ print "" }} +/* + This file is generated by ./cmd/enbas-cli-generators + DO NOT EDIT. +*/ {{ range $name, $command := . }} {{- $struct_name := capitalise $name | printf "%sExecutor" -}} {{- $new_executor_function_name := capitalise $name | printf "New%sExecutor" -}} @@ -16,7 +21,7 @@ type {{ $struct_name }} struct { {{- end }} {{- range $flag := $command.Flags -}} {{ print "" }} - {{ convertFlagToMixedCaps $flag.Flag }} {{ getFlagType $flag.Flag }} + {{ flagFieldName $flag }} {{ getFlagType $flag.Flag }} {{- end -}} {{- range $field := $command.AdditionalFields -}} {{ print "" }} @@ -58,10 +63,10 @@ func {{ $new_executor_function_name }}( {{- range $flag := $command.Flags -}} {{- if eq (getFlagType $flag.Flag) "string" -}} {{ print "" }} - exe.StringVar(&exe.{{ convertFlagToMixedCaps $flag.Flag }}, {{ printf "%q" $flag.Flag }}, {{ printf "%q" $flag.Default }}, {{ getFlagDescription $flag.Flag | printf "%q" }}) + exe.StringVar(&exe.{{ flagFieldName $flag }}, {{ printf "%q" $flag.Flag }}, {{ printf "%q" $flag.Default }}, {{ getFlagDescription $flag.Flag | printf "%q" }}) {{- else if eq (getFlagType $flag.Flag) "bool" -}} {{ print "" }} - exe.BoolVar(&exe.{{ convertFlagToMixedCaps $flag.Flag }}, {{ printf "%q" $flag.Flag }}, {{ $flag.Default }}, {{ getFlagDescription $flag.Flag | printf "%q" }}) + exe.BoolVar(&exe.{{ flagFieldName $flag }}, {{ printf "%q" $flag.Flag }}, {{ $flag.Default }}, {{ getFlagDescription $flag.Flag | printf "%q" }}) {{- end -}} {{- end -}} {{ print "" }} diff --git a/cmd/enbas/main.go b/cmd/enbas/main.go index 8d1822e..8d44176 100644 --- a/cmd/enbas/main.go +++ b/cmd/enbas/main.go @@ -89,11 +89,9 @@ func run() error { } executorMap := map[string]executor.Executor{ - executor.CommandAccept: executor.NewAcceptOrRejectExecutor( + executor.CommandAccept: executor.NewAcceptExecutor( enbasPrinter, enbasConfig, - executor.CommandAccept, - executor.CommandSummaryLookup(executor.CommandAccept), ), executor.CommandAdd: executor.NewAddExecutor( enbasPrinter, @@ -125,17 +123,13 @@ func run() error { executor.CommandEdit, executor.CommandSummaryLookup(executor.CommandEdit), ), - executor.CommandFollow: executor.NewFollowOrUnfollowExecutor( + executor.CommandFollow: executor.NewFollowExecutor( enbasPrinter, enbasConfig, - executor.CommandFollow, - executor.CommandSummaryLookup(executor.CommandFollow), ), executor.CommandInit: executor.NewInitExecutor( enbasPrinter, configDir, - executor.CommandInit, - executor.CommandSummaryLookup(executor.CommandInit), ), executor.CommandLogin: executor.NewLoginExecutor( enbasPrinter, @@ -147,11 +141,9 @@ func run() error { executor.CommandMute, executor.CommandSummaryLookup(executor.CommandMute), ), - executor.CommandReject: executor.NewAcceptOrRejectExecutor( + executor.CommandReject: executor.NewRejectExecutor( enbasPrinter, enbasConfig, - executor.CommandReject, - executor.CommandSummaryLookup(executor.CommandReject), ), executor.CommandRemove: executor.NewRemoveExecutor( enbasPrinter, @@ -163,11 +155,9 @@ func run() error { enbasPrinter, enbasConfig, ), - executor.CommandUnfollow: executor.NewFollowOrUnfollowExecutor( + executor.CommandUnfollow: executor.NewUnfollowExecutor( enbasPrinter, enbasConfig, - executor.CommandUnfollow, - executor.CommandSummaryLookup(executor.CommandUnfollow), ), executor.CommandUnmute: executor.NewMuteOrUnmuteExecutor( enbasPrinter, diff --git a/internal/executor/accept.go b/internal/executor/accept.go new file mode 100644 index 0000000..158927d --- /dev/null +++ b/internal/executor/accept.go @@ -0,0 +1,40 @@ +package executor + +import ( + "fmt" + + "codeflow.dananglin.me.uk/apollo/enbas/internal/client" +) + +func (a *AcceptExecutor) Execute() error { + funcMap := map[string]func(*client.Client) error{ + resourceFollowRequest: a.acceptFollowRequest, + } + + doFunc, ok := funcMap[a.resourceType] + if !ok { + return UnsupportedTypeError{resourceType: a.resourceType} + } + + gtsClient, err := client.NewClientFromFile(a.config.CredentialsFile) + if err != nil { + return fmt.Errorf("unable to create the GoToSocial client: %w", err) + } + + return doFunc(gtsClient) +} + +func (a *AcceptExecutor) acceptFollowRequest(gtsClient *client.Client) error { + accountID, err := getAccountID(gtsClient, false, a.accountName, a.config.CredentialsFile) + if err != nil { + return fmt.Errorf("received an error while getting the account ID: %w", err) + } + + if err := gtsClient.AcceptFollowRequest(accountID); err != nil { + return fmt.Errorf("unable to accept the follow request: %w", err) + } + + a.printer.PrintSuccess("Successfully accepted the follow request.") + + return nil +} diff --git a/internal/executor/accept_or_reject.go b/internal/executor/accept_or_reject.go deleted file mode 100644 index 71b3ff7..0000000 --- a/internal/executor/accept_or_reject.go +++ /dev/null @@ -1,91 +0,0 @@ -package executor - -import ( - "flag" - "fmt" - - "codeflow.dananglin.me.uk/apollo/enbas/internal/client" - "codeflow.dananglin.me.uk/apollo/enbas/internal/config" - "codeflow.dananglin.me.uk/apollo/enbas/internal/printer" -) - -type AcceptOrRejectExecutor struct { - *flag.FlagSet - - printer *printer.Printer - config *config.Config - resourceType string - accountName string - command string -} - -func NewAcceptOrRejectExecutor(enbasPrinter *printer.Printer, config *config.Config, name, summary string) *AcceptOrRejectExecutor { - acceptExe := AcceptOrRejectExecutor{ - FlagSet: flag.NewFlagSet(name, flag.ExitOnError), - - printer: enbasPrinter, - config: config, - command: name, - } - - acceptExe.StringVar(&acceptExe.resourceType, flagType, "", "Specify the type of resource to accept or reject") - acceptExe.StringVar(&acceptExe.accountName, flagAccountName, "", "Specify the account name in full (username@domain)") - - acceptExe.Usage = commandUsageFunc(name, summary, acceptExe.FlagSet) - - return &acceptExe -} - -func (a *AcceptOrRejectExecutor) Execute() error { - funcMap := map[string]func(*client.Client) error{ - resourceFollowRequest: a.acceptOrRejectFollowRequest, - } - - doFunc, ok := funcMap[a.resourceType] - if !ok { - return UnsupportedTypeError{resourceType: a.resourceType} - } - - gtsClient, err := client.NewClientFromFile(a.config.CredentialsFile) - if err != nil { - return fmt.Errorf("unable to create the GoToSocial client: %w", err) - } - - return doFunc(gtsClient) -} - -func (a *AcceptOrRejectExecutor) acceptOrRejectFollowRequest(gtsClient *client.Client) error { - accountID, err := getAccountID(gtsClient, false, a.accountName, a.config.CredentialsFile) - if err != nil { - return fmt.Errorf("received an error while getting the account ID: %w", err) - } - - switch a.command { - case CommandAccept: - return a.acceptFollowRequest(gtsClient, accountID) - case CommandReject: - return a.rejectFollowRequest(gtsClient, accountID) - default: - return nil - } -} - -func (a *AcceptOrRejectExecutor) acceptFollowRequest(gtsClient *client.Client, accountID string) error { - if err := gtsClient.AcceptFollowRequest(accountID); err != nil { - return fmt.Errorf("unable to accept the follow request: %w", err) - } - - a.printer.PrintSuccess("Successfully accepted the follow request.") - - return nil -} - -func (a *AcceptOrRejectExecutor) rejectFollowRequest(gtsClient *client.Client, accountID string) error { - if err := gtsClient.RejectFollowRequest(accountID); err != nil { - return fmt.Errorf("unable to reject the follow request: %w", err) - } - - a.printer.PrintSuccess("Successfully rejected the follow request.") - - return nil -} diff --git a/internal/executor/executors.go b/internal/executor/executors.go index b38ba44..0f20ba0 100644 --- a/internal/executor/executors.go +++ b/internal/executor/executors.go @@ -7,6 +7,67 @@ import ( "codeflow.dananglin.me.uk/apollo/enbas/internal/printer" ) +/* + This file is generated by ./cmd/enbas-cli-generators + DO NOT EDIT. +*/ + +// AcceptExecutor is the executor for the accept command. +type AcceptExecutor struct { + *flag.FlagSet + printer *printer.Printer + config *config.Config + accountName string + resourceType string +} + +func NewAcceptExecutor( + printer *printer.Printer, + config *config.Config, +) *AcceptExecutor { + exe := AcceptExecutor{ + FlagSet: flag.NewFlagSet("accept", flag.ExitOnError), + printer: printer, + config: config, + } + + exe.Usage = commandUsageFunc("accept", "Accepts a request (e.g. a follow request)", exe.FlagSet) + + exe.StringVar(&exe.accountName, "account-name", "", "The name of the account") + exe.StringVar(&exe.resourceType, "type", "", "The type of resource you want to action on (e.g. account, status)") + return &exe +} + +// FollowExecutor is the executor for the follow command. +type FollowExecutor struct { + *flag.FlagSet + printer *printer.Printer + config *config.Config + accountName string + notify bool + showReposts bool + resourceType string +} + +func NewFollowExecutor( + printer *printer.Printer, + config *config.Config, +) *FollowExecutor { + exe := FollowExecutor{ + FlagSet: flag.NewFlagSet("follow", flag.ExitOnError), + printer: printer, + config: config, + } + + exe.Usage = commandUsageFunc("follow", "Follow a resource (e.g. an account)", exe.FlagSet) + + exe.StringVar(&exe.accountName, "account-name", "", "The name of the account") + exe.BoolVar(&exe.notify, "notify", false, "Get notifications from statuses from the account you want to follow") + exe.BoolVar(&exe.showReposts, "show-reposts", true, "Show reposts from the account you want to follow") + exe.StringVar(&exe.resourceType, "type", "", "The type of resource you want to action on (e.g. account, status)") + return &exe +} + // InitExecutor is the executor for the init command. type InitExecutor struct { *flag.FlagSet @@ -53,6 +114,32 @@ func NewLoginExecutor( return &exe } +// RejectExecutor is the executor for the reject command. +type RejectExecutor struct { + *flag.FlagSet + printer *printer.Printer + config *config.Config + accountName string + resourceType string +} + +func NewRejectExecutor( + printer *printer.Printer, + config *config.Config, +) *RejectExecutor { + exe := RejectExecutor{ + FlagSet: flag.NewFlagSet("reject", flag.ExitOnError), + printer: printer, + config: config, + } + + exe.Usage = commandUsageFunc("reject", "Rejects a request (e.g. a follow request)", exe.FlagSet) + + exe.StringVar(&exe.accountName, "account-name", "", "The name of the account") + exe.StringVar(&exe.resourceType, "type", "", "The type of resource you want to action on (e.g. account, status)") + return &exe +} + // SwitchExecutor is the executor for the switch command. type SwitchExecutor struct { *flag.FlagSet @@ -79,6 +166,32 @@ func NewSwitchExecutor( return &exe } +// UnfollowExecutor is the executor for the unfollow command. +type UnfollowExecutor struct { + *flag.FlagSet + printer *printer.Printer + config *config.Config + accountName string + resourceType string +} + +func NewUnfollowExecutor( + printer *printer.Printer, + config *config.Config, +) *UnfollowExecutor { + exe := UnfollowExecutor{ + FlagSet: flag.NewFlagSet("unfollow", flag.ExitOnError), + printer: printer, + config: config, + } + + exe.Usage = commandUsageFunc("unfollow", "Unfollow a resource (e.g. an account)", exe.FlagSet) + + exe.StringVar(&exe.accountName, "account-name", "", "The name of the account") + exe.StringVar(&exe.resourceType, "type", "", "The type of resource you want to action on (e.g. account, status)") + return &exe +} + // VersionExecutor is the executor for the version command. type VersionExecutor struct { *flag.FlagSet diff --git a/internal/executor/follow.go b/internal/executor/follow.go new file mode 100644 index 0000000..b76ca09 --- /dev/null +++ b/internal/executor/follow.go @@ -0,0 +1,46 @@ +package executor + +import ( + "fmt" + + "codeflow.dananglin.me.uk/apollo/enbas/internal/client" +) + +func (f *FollowExecutor) Execute() error { + funcMap := map[string]func(*client.Client) error{ + resourceAccount: f.followAccount, + } + + doFunc, ok := funcMap[f.resourceType] + if !ok { + return UnsupportedTypeError{resourceType: f.resourceType} + } + + gtsClient, err := client.NewClientFromFile(f.config.CredentialsFile) + if err != nil { + return fmt.Errorf("unable to create the GoToSocial client: %w", err) + } + + return doFunc(gtsClient) +} + +func (f *FollowExecutor) followAccount(gtsClient *client.Client) error { + accountID, err := getAccountID(gtsClient, false, f.accountName, f.config.CredentialsFile) + if err != nil { + return fmt.Errorf("received an error while getting the account ID: %w", err) + } + + form := client.FollowAccountForm{ + AccountID: accountID, + ShowReposts: f.showReposts, + Notify: f.notify, + } + + if err := gtsClient.FollowAccount(form); err != nil { + return fmt.Errorf("unable to follow the account: %w", err) + } + + f.printer.PrintSuccess("Successfully sent the follow request.") + + return nil +} diff --git a/internal/executor/follow_or_unfollow.go b/internal/executor/follow_or_unfollow.go deleted file mode 100644 index eb7d15f..0000000 --- a/internal/executor/follow_or_unfollow.go +++ /dev/null @@ -1,101 +0,0 @@ -package executor - -import ( - "flag" - "fmt" - - "codeflow.dananglin.me.uk/apollo/enbas/internal/client" - "codeflow.dananglin.me.uk/apollo/enbas/internal/config" - "codeflow.dananglin.me.uk/apollo/enbas/internal/printer" -) - -type FollowOrUnfollowExecutor struct { - *flag.FlagSet - - printer *printer.Printer - config *config.Config - resourceType string - accountName string - showReposts bool - notify bool - action string -} - -func NewFollowOrUnfollowExecutor(printer *printer.Printer, config *config.Config, name, summary string) *FollowOrUnfollowExecutor { - command := FollowOrUnfollowExecutor{ - FlagSet: flag.NewFlagSet(name, flag.ExitOnError), - - printer: printer, - config: config, - action: name, - } - - command.StringVar(&command.resourceType, flagType, "", "Specify the type of resource to follow") - command.StringVar(&command.accountName, flagAccountName, "", "Specify the account name in full (username@domain)") - command.BoolVar(&command.showReposts, flagShowReposts, true, "Show reposts from the account you want to follow") - command.BoolVar(&command.notify, flagNotify, false, "Get notifications when the account you want to follow posts a status") - - command.Usage = commandUsageFunc(name, summary, command.FlagSet) - - return &command -} - -func (f *FollowOrUnfollowExecutor) Execute() error { - funcMap := map[string]func(*client.Client) error{ - resourceAccount: f.followOrUnfollowAccount, - } - - doFunc, ok := funcMap[f.resourceType] - if !ok { - return UnsupportedTypeError{resourceType: f.resourceType} - } - - gtsClient, err := client.NewClientFromFile(f.config.CredentialsFile) - if err != nil { - return fmt.Errorf("unable to create the GoToSocial client: %w", err) - } - - return doFunc(gtsClient) -} - -func (f *FollowOrUnfollowExecutor) followOrUnfollowAccount(gtsClient *client.Client) error { - accountID, err := getAccountID(gtsClient, false, f.accountName, f.config.CredentialsFile) - if err != nil { - return fmt.Errorf("received an error while getting the account ID: %w", err) - } - - switch f.action { - case CommandFollow: - return f.followAccount(gtsClient, accountID) - case CommandUnfollow: - return f.unfollowAccount(gtsClient, accountID) - default: - return nil - } -} - -func (f *FollowOrUnfollowExecutor) followAccount(gtsClient *client.Client, accountID string) error { - form := client.FollowAccountForm{ - AccountID: accountID, - ShowReposts: f.showReposts, - Notify: f.notify, - } - - if err := gtsClient.FollowAccount(form); err != nil { - return fmt.Errorf("unable to follow the account: %w", err) - } - - f.printer.PrintSuccess("Successfully sent the follow request.") - - return nil -} - -func (f *FollowOrUnfollowExecutor) unfollowAccount(gtsClient *client.Client, accountID string) error { - if err := gtsClient.UnfollowAccount(accountID); err != nil { - return fmt.Errorf("unable to unfollow the account: %w", err) - } - - f.printer.PrintSuccess("Successfully unfollowed the account.") - - return nil -} diff --git a/internal/executor/reject.go b/internal/executor/reject.go new file mode 100644 index 0000000..adaf804 --- /dev/null +++ b/internal/executor/reject.go @@ -0,0 +1,40 @@ +package executor + +import ( + "fmt" + + "codeflow.dananglin.me.uk/apollo/enbas/internal/client" +) + +func (r *RejectExecutor) Execute() error { + funcMap := map[string]func(*client.Client) error{ + resourceFollowRequest: r.rejectFollowRequest, + } + + doFunc, ok := funcMap[r.resourceType] + if !ok { + return UnsupportedTypeError{resourceType: r.resourceType} + } + + gtsClient, err := client.NewClientFromFile(r.config.CredentialsFile) + if err != nil { + return fmt.Errorf("unable to create the GoToSocial client: %w", err) + } + + return doFunc(gtsClient) +} + +func (r *RejectExecutor) rejectFollowRequest(gtsClient *client.Client) error { + accountID, err := getAccountID(gtsClient, false, r.accountName, r.config.CredentialsFile) + if err != nil { + return fmt.Errorf("received an error while getting the account ID: %w", err) + } + + if err := gtsClient.RejectFollowRequest(accountID); err != nil { + return fmt.Errorf("unable to reject the follow request: %w", err) + } + + r.printer.PrintSuccess("Successfully rejected the follow request.") + + return nil +} diff --git a/internal/executor/unfollow.go b/internal/executor/unfollow.go new file mode 100644 index 0000000..102ce3d --- /dev/null +++ b/internal/executor/unfollow.go @@ -0,0 +1,40 @@ +package executor + +import ( + "fmt" + + "codeflow.dananglin.me.uk/apollo/enbas/internal/client" +) + +func (f *UnfollowExecutor) Execute() error { + funcMap := map[string]func(*client.Client) error{ + resourceAccount: f.unfollowAccount, + } + + doFunc, ok := funcMap[f.resourceType] + if !ok { + return UnsupportedTypeError{resourceType: f.resourceType} + } + + gtsClient, err := client.NewClientFromFile(f.config.CredentialsFile) + if err != nil { + return fmt.Errorf("unable to create the GoToSocial client: %w", err) + } + + return doFunc(gtsClient) +} + +func (f *UnfollowExecutor) unfollowAccount(gtsClient *client.Client) error { + accountID, err := getAccountID(gtsClient, false, f.accountName, f.config.CredentialsFile) + if err != nil { + return fmt.Errorf("received an error while getting the account ID: %w", err) + } + + if err := gtsClient.UnfollowAccount(accountID); err != nil { + return fmt.Errorf("unable to unfollow the account: %w", err) + } + + f.printer.PrintSuccess("Successfully unfollowed the account.") + + return nil +} diff --git a/schema/enbas_cli_schema.json b/schema/enbas_cli_schema.json index 652d226..6401def 100644 --- a/schema/enbas_cli_schema.json +++ b/schema/enbas_cli_schema.json @@ -1,8 +1,8 @@ { "flags": { "account-name": { - "type": "string", - "description": "The name of the account" + "type": "string", + "description": "The name of the account" }, "full": { "type": "bool", @@ -12,6 +12,18 @@ "type": "string", "description": "The instance that you want to log into" }, + "notify": { + "type": "bool", + "description": "Get notifications from statuses from the account you want to follow" + }, + "show-reposts": { + "type": "bool", + "description": "Show reposts from the account you want to follow" + }, + "type": { + "type": "string", + "description": "The type of resource you want to action on (e.g. account, status)" + }, "to": { "type": "string", "description": "TBC" @@ -19,6 +31,28 @@ }, "commands": { + "accept": { + "additionalFields": [], + "flags": [ + { "flag": "account-name", "default": "" }, + { "flag": "type", "fieldName": "resourceType", "default": "" } + ], + "summary": "Accepts a request (e.g. a follow request)", + "useConfig": true, + "usePrinter": true + }, + "follow": { + "additionalFields": [], + "flags": [ + { "flag": "account-name", "default": "" }, + { "flag": "notify", "default": "false" }, + { "flag": "show-reposts", "default": "true" }, + { "flag": "type", "fieldName": "resourceType", "default": "" } + ], + "summary": "Follow a resource (e.g. an account)", + "useConfig": true, + "usePrinter": true + }, "init": { "additionalFields": [ { "name": "configDir", "type": "string"} @@ -29,6 +63,7 @@ "usePrinter": true }, "login": { + "additionalFields": [], "flags": [ { "flag": "instance", "default": "" } ], @@ -36,7 +71,18 @@ "useConfig": true, "usePrinter": true }, + "reject": { + "additionalFields": [], + "flags": [ + { "flag": "account-name", "default": "" }, + { "flag": "type", "fieldName": "resourceType", "default": "" } + ], + "summary": "Rejects a request (e.g. a follow request)", + "useConfig": true, + "usePrinter": true + }, "switch": { + "additionalFields": [], "flags": [ { "flag": "account-name", "default": "" }, { "flag": "to", "default": "" } @@ -45,6 +91,16 @@ "useConfig": true, "usePrinter": true }, + "unfollow": { + "additionalFields": [], + "flags": [ + { "flag": "account-name", "default": "" }, + { "flag": "type", "fieldName": "resourceType", "default": "" } + ], + "summary": "Unfollow a resource (e.g. an account)", + "useConfig": true, + "usePrinter": true + }, "version": { "additionalFields": [ { "name": "binaryVersion", "type": "string"},