Compare commits
2 commits
3e9290897c
...
e7f857cf4f
Author | SHA1 | Date | |
---|---|---|---|
e7f857cf4f | |||
8ae4085d84 |
29 changed files with 1022 additions and 933 deletions
147
cmd/enbas/add.go
147
cmd/enbas/add.go
|
@ -1,147 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type addCommand struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
resourceType string
|
||||
toResourceType string
|
||||
listID string
|
||||
accountNames accountNames
|
||||
content string
|
||||
}
|
||||
|
||||
func newAddCommand(tlf topLevelFlags, name, summary string) *addCommand {
|
||||
emptyArr := make([]string, 0, 3)
|
||||
|
||||
command := addCommand{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
accountNames: accountNames(emptyArr),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
command.StringVar(&command.resourceType, flagType, "", "specify the resource type to add (e.g. account, note)")
|
||||
command.StringVar(&command.toResourceType, flagTo, "", "specify the target resource type to add to (e.g. list, account, etc)")
|
||||
command.StringVar(&command.listID, flagListID, "", "the ID of the list to add to")
|
||||
command.Var(&command.accountNames, flagAccountName, "the name of the account to add to the resource")
|
||||
command.StringVar(&command.content, flagContent, "", "the content of the note")
|
||||
|
||||
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
func (c *addCommand) Execute() error {
|
||||
if c.toResourceType == "" {
|
||||
return flagNotSetError{flagText: flagTo}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceList: c.addToList,
|
||||
resourceAccount: c.addToAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.toResourceType]
|
||||
if !ok {
|
||||
return unsupportedResourceTypeError{resourceType: c.toResourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *addCommand) addToList(gtsClient *client.Client) error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceAccount: c.addAccountsToList,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedAddOperationError{
|
||||
ResourceType: c.resourceType,
|
||||
AddToResourceType: c.toResourceType,
|
||||
}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *addCommand) addAccountsToList(gtsClient *client.Client) error {
|
||||
if c.listID == "" {
|
||||
return flagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
if len(c.accountNames) == 0 {
|
||||
return noAccountSpecifiedError{}
|
||||
}
|
||||
|
||||
accountIDs := make([]string, len(c.accountNames))
|
||||
|
||||
for i := range c.accountNames {
|
||||
accountID, err := getTheirAccountID(gtsClient, c.accountNames[i])
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get the account ID for %s, %w", c.accountNames[i], err)
|
||||
}
|
||||
|
||||
accountIDs[i] = accountID
|
||||
}
|
||||
|
||||
if err := gtsClient.AddAccountsToList(c.listID, accountIDs); err != nil {
|
||||
return fmt.Errorf("unable to add the accounts to the list; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully added the account(s) to the list.")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *addCommand) addToAccount(gtsClient *client.Client) error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceNote: c.addNoteToAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedAddOperationError{
|
||||
ResourceType: c.resourceType,
|
||||
AddToResourceType: c.toResourceType,
|
||||
}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *addCommand) addNoteToAccount(gtsClient *client.Client) error {
|
||||
if len(c.accountNames) != 1 {
|
||||
return fmt.Errorf("unexpected number of accounts specified; want 1, got %d", len(c.accountNames))
|
||||
}
|
||||
|
||||
accountID, err := getAccountID(gtsClient, false, c.accountNames[0], c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
||||
if c.content == "" {
|
||||
return errors.New("the note content should not be empty")
|
||||
}
|
||||
|
||||
if err := gtsClient.SetPrivateNote(accountID, c.content); err != nil {
|
||||
return fmt.Errorf("unable to add the private note to the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully added the private note to the account.")
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type blockCommand struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
resourceType string
|
||||
accountName string
|
||||
unblock bool
|
||||
}
|
||||
|
||||
func newBlockCommand(tlf topLevelFlags, name, summary string, unblock bool) *blockCommand {
|
||||
command := blockCommand{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
|
||||
topLevelFlags: tlf,
|
||||
unblock: unblock,
|
||||
}
|
||||
|
||||
command.StringVar(&command.resourceType, flagType, "", "specify the type of resource to block or unblock")
|
||||
command.StringVar(&command.accountName, flagAccountName, "", "specify the account name in full (username@domain)")
|
||||
|
||||
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
func (c *blockCommand) Execute() error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceAccount: c.blockAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedResourceTypeError{resourceType: c.resourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *blockCommand) blockAccount(gtsClient *client.Client) error {
|
||||
accountID, err := getAccountID(gtsClient, false, c.accountName, c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
||||
if c.unblock {
|
||||
return c.unblockAccount(gtsClient, accountID)
|
||||
}
|
||||
|
||||
if err := gtsClient.BlockAccount(accountID); err != nil {
|
||||
return fmt.Errorf("unable to block the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully blocked the account.")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *blockCommand) unblockAccount(gtsClient *client.Client, accountID string) error {
|
||||
if err := gtsClient.UnblockAccount(accountID); err != nil {
|
||||
return fmt.Errorf("unable to unblock the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully unblocked the account.")
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type deleteCommand struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
resourceType string
|
||||
listID string
|
||||
}
|
||||
|
||||
func newDeleteCommand(tlf topLevelFlags, name, summary string) *deleteCommand {
|
||||
command := deleteCommand{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
command.StringVar(&command.resourceType, flagType, "", "specify the type of resource to delete")
|
||||
command.StringVar(&command.listID, flagListID, "", "specify the ID of the list to delete")
|
||||
|
||||
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
func (c *deleteCommand) Execute() error {
|
||||
if c.resourceType == "" {
|
||||
return flagNotSetError{flagText: flagType}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceList: c.deleteList,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedResourceTypeError{resourceType: c.resourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *deleteCommand) deleteList(gtsClient *client.Client) error {
|
||||
if c.listID == "" {
|
||||
return flagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
if err := gtsClient.DeleteList(c.listID); err != nil {
|
||||
return fmt.Errorf("unable to delete the list; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("The list was successfully deleted.")
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,57 +1,9 @@
|
|||
package main
|
||||
|
||||
type flagNotSetError struct {
|
||||
flagText string
|
||||
}
|
||||
|
||||
func (e flagNotSetError) Error() string {
|
||||
return "the flag '" + e.flagText + "' is not set"
|
||||
}
|
||||
|
||||
type unsupportedResourceTypeError struct {
|
||||
resourceType string
|
||||
}
|
||||
|
||||
func (e unsupportedResourceTypeError) Error() string {
|
||||
return "unsupported resource type '" + e.resourceType + "'"
|
||||
}
|
||||
|
||||
type invalidTimelineCategoryError struct {
|
||||
category string
|
||||
}
|
||||
|
||||
func (e invalidTimelineCategoryError) Error() string {
|
||||
return "'" + e.category + "' is not a valid timeline category (please choose home, public, tag or list)"
|
||||
}
|
||||
|
||||
type unknownSubcommandError struct {
|
||||
type unknownCommandError struct {
|
||||
subcommand string
|
||||
}
|
||||
|
||||
func (e unknownSubcommandError) Error() string {
|
||||
return "unknown subcommand '" + e.subcommand + "'"
|
||||
}
|
||||
|
||||
type noAccountSpecifiedError struct{}
|
||||
|
||||
func (e noAccountSpecifiedError) Error() string {
|
||||
return "no account specified in this request"
|
||||
}
|
||||
|
||||
type unsupportedAddOperationError struct {
|
||||
ResourceType string
|
||||
AddToResourceType string
|
||||
}
|
||||
|
||||
func (e unsupportedAddOperationError) Error() string {
|
||||
return "adding '" + e.ResourceType + "' to '" + e.AddToResourceType + "' is not supported"
|
||||
}
|
||||
|
||||
type unsupportedRemoveOperationError struct {
|
||||
ResourceType string
|
||||
RemoveFromResourceType string
|
||||
}
|
||||
|
||||
func (e unsupportedRemoveOperationError) Error() string {
|
||||
return "removing '" + e.ResourceType + "' from '" + e.RemoveFromResourceType + "' is not supported"
|
||||
func (e unknownCommandError) Error() string {
|
||||
return "unknown command '" + e.subcommand + "'"
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package main
|
||||
|
||||
import "strings"
|
||||
|
||||
type accountNames []string
|
||||
|
||||
func (a *accountNames) String() string {
|
||||
return strings.Join(*a, ", ")
|
||||
}
|
||||
|
||||
func (a *accountNames) Set(value string) error {
|
||||
if len(value) > 0 {
|
||||
*a = append(*a, value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type topLevelFlags struct {
|
||||
configDir string
|
||||
}
|
|
@ -4,47 +4,36 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/executor"
|
||||
)
|
||||
|
||||
const (
|
||||
flagAccountName = "account-name"
|
||||
flagTo = "to"
|
||||
flagContent = "content"
|
||||
flagInstance = "instance"
|
||||
flagLimit = "limit"
|
||||
flagListID = "list-id"
|
||||
flagListTitle = "list-title"
|
||||
flagListRepliesPolicy = "list-replies-policy"
|
||||
flagMyAccount = "my-account"
|
||||
flagNotify = "notify"
|
||||
flagFrom = "from"
|
||||
flagType = "type"
|
||||
flagShowRelationship = "show-relationship"
|
||||
flagShowPreferences = "show-preferences"
|
||||
flagShowReposts = "show-reposts"
|
||||
flagStatusID = "status-id"
|
||||
flagTag = "tag"
|
||||
flagTimelineCategory = "timeline-category"
|
||||
commandLogin string = "login"
|
||||
commandVersion string = "version"
|
||||
commandShow string = "show"
|
||||
commandSwitch string = "switch"
|
||||
commandCreate string = "create"
|
||||
commandDelete string = "delete"
|
||||
commandEdit string = "edit"
|
||||
commandWhoami string = "whoami"
|
||||
commandAdd string = "add"
|
||||
commandRemove string = "remove"
|
||||
commandFollow string = "follow"
|
||||
commandUnfollow string = "unfollow"
|
||||
commandBlock string = "block"
|
||||
commandUnblock string = "unblock"
|
||||
)
|
||||
|
||||
const (
|
||||
resourceAccount = "account"
|
||||
resourceBlocked = "blocked"
|
||||
resourceFollowers = "followers"
|
||||
resourceFollowing = "following"
|
||||
resourceInstance = "instance"
|
||||
resourceList = "list"
|
||||
resourceNote = "note"
|
||||
resourceStatus = "status"
|
||||
resourceTimeline = "timeline"
|
||||
var (
|
||||
binaryVersion string
|
||||
buildTime string
|
||||
goVersion string
|
||||
gitCommit string
|
||||
)
|
||||
|
||||
type Executor interface {
|
||||
Name() string
|
||||
Parse(args []string) error
|
||||
Execute() error
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
fmt.Printf("ERROR: %v.\n", err)
|
||||
|
@ -53,31 +42,14 @@ func main() {
|
|||
}
|
||||
|
||||
func run() error {
|
||||
const (
|
||||
commandLogin string = "login"
|
||||
commandVersion string = "version"
|
||||
commandShow string = "show"
|
||||
commandSwitchAccount string = "switch-account"
|
||||
commandCreate string = "create"
|
||||
commandDelete string = "delete"
|
||||
commandUpdate string = "update"
|
||||
commandWhoami string = "whoami"
|
||||
commandAdd string = "add"
|
||||
commandRemove string = "remove"
|
||||
commandFollow string = "follow"
|
||||
commandUnfollow string = "unfollow"
|
||||
commandBlock string = "block"
|
||||
commandUnblock string = "unblock"
|
||||
)
|
||||
|
||||
commandSummaries := map[string]string{
|
||||
commandLogin: "login to an account on GoToSocial",
|
||||
commandVersion: "print the application's version and build information",
|
||||
commandShow: "print details about a specified resource",
|
||||
commandSwitchAccount: "switch to a different account",
|
||||
commandSwitch: "switch to a different account",
|
||||
commandCreate: "create a specific resource",
|
||||
commandDelete: "delete a specific resource",
|
||||
commandUpdate: "update a specific resource",
|
||||
commandEdit: "edit a specific resource",
|
||||
commandWhoami: "print the account that you are currently logged in to",
|
||||
commandAdd: "add a resource to another resource",
|
||||
commandRemove: "remove a resource from another resource",
|
||||
|
@ -87,11 +59,11 @@ func run() error {
|
|||
commandUnblock: "unblock a resource (e.g. an account)",
|
||||
}
|
||||
|
||||
tlf := topLevelFlags{}
|
||||
topLevelFlags := executor.TopLevelFlags{}
|
||||
|
||||
flag.StringVar(&tlf.configDir, "config-dir", "", "specify your config directory")
|
||||
flag.StringVar(&topLevelFlags.ConfigDir, "config-dir", "", "specify your config directory")
|
||||
|
||||
flag.Usage = enbasUsageFunc(commandSummaries)
|
||||
flag.Usage = usageFunc(commandSummaries)
|
||||
|
||||
flag.Parse()
|
||||
|
||||
|
@ -104,54 +76,143 @@ func run() error {
|
|||
command := flag.Arg(0)
|
||||
args := flag.Args()[1:]
|
||||
|
||||
// TODO: will not be needed anymore
|
||||
var executor Executor
|
||||
var err error
|
||||
|
||||
switch command {
|
||||
case commandLogin:
|
||||
executor = newLoginCommand(tlf, commandLogin, commandSummaries[commandLogin])
|
||||
case commandVersion:
|
||||
executor = newVersionCommand(commandVersion, commandSummaries[commandVersion])
|
||||
case commandShow:
|
||||
executor = newShowCommand(tlf, commandShow, commandSummaries[commandShow])
|
||||
case commandSwitchAccount:
|
||||
executor = newSwitchCommand(tlf, commandSwitchAccount, commandSummaries[commandSwitchAccount])
|
||||
case commandCreate:
|
||||
executor = newCreateCommand(tlf, commandCreate, commandSummaries[commandCreate])
|
||||
case commandDelete:
|
||||
executor = newDeleteCommand(tlf, commandDelete, commandSummaries[commandDelete])
|
||||
case commandUpdate:
|
||||
executor = newUpdateCommand(tlf, commandUpdate, commandSummaries[commandUpdate])
|
||||
case commandWhoami:
|
||||
executor = newWhoAmICommand(tlf, commandWhoami, commandSummaries[commandWhoami])
|
||||
case commandAdd:
|
||||
executor = newAddCommand(tlf, commandAdd, commandSummaries[commandAdd])
|
||||
case commandRemove:
|
||||
executor = newRemoveCommand(tlf, commandRemove, commandSummaries[commandRemove])
|
||||
case commandFollow:
|
||||
executor = newFollowCommand(tlf, commandFollow, commandSummaries[commandFollow], false)
|
||||
case commandUnfollow:
|
||||
executor = newFollowCommand(tlf, commandUnfollow, commandSummaries[commandUnfollow], true)
|
||||
exe := executor.NewAddExecutor(
|
||||
topLevelFlags,
|
||||
commandAdd,
|
||||
commandSummaries[commandAdd],
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandBlock:
|
||||
executor = newBlockCommand(tlf, commandBlock, commandSummaries[commandBlock], false)
|
||||
exe := executor.NewBlockExecutor(
|
||||
topLevelFlags,
|
||||
commandBlock,
|
||||
commandSummaries[commandBlock],
|
||||
false,
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandCreate:
|
||||
exe := executor.NewCreateExecutor(
|
||||
topLevelFlags,
|
||||
commandCreate,
|
||||
commandSummaries[commandCreate],
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandDelete:
|
||||
exe := executor.NewDeleteExecutor(
|
||||
topLevelFlags,
|
||||
commandDelete,
|
||||
commandSummaries[commandDelete],
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandEdit:
|
||||
exe := executor.NewEditExecutor(
|
||||
topLevelFlags,
|
||||
commandEdit,
|
||||
commandSummaries[commandEdit],
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandFollow:
|
||||
exe := executor.NewFollowExecutor(
|
||||
topLevelFlags,
|
||||
commandFollow,
|
||||
commandSummaries[commandFollow],
|
||||
false,
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandLogin:
|
||||
exe := executor.NewLoginExecutor(
|
||||
topLevelFlags,
|
||||
commandLogin,
|
||||
commandSummaries[commandLogin],
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandRemove:
|
||||
exe := executor.NewRemoveExecutor(
|
||||
topLevelFlags,
|
||||
commandRemove,
|
||||
commandSummaries[commandRemove],
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandSwitch:
|
||||
exe := executor.NewSwitchExecutor(
|
||||
topLevelFlags,
|
||||
commandSwitch,
|
||||
commandSummaries[commandSwitch],
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandUnfollow:
|
||||
exe := executor.NewFollowExecutor(topLevelFlags, commandUnfollow, commandSummaries[commandUnfollow], true)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandUnblock:
|
||||
executor = newBlockCommand(tlf, commandUnblock, commandSummaries[commandUnblock], true)
|
||||
exe := executor.NewBlockExecutor(topLevelFlags, commandUnblock, commandSummaries[commandUnblock], true)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandShow:
|
||||
exe := executor.NewShowExecutor(topLevelFlags, commandShow, commandSummaries[commandShow])
|
||||
err = executor.Execute(exe, args)
|
||||
case commandVersion:
|
||||
exe := executor.NewVersionExecutor(
|
||||
commandVersion,
|
||||
commandSummaries[commandVersion],
|
||||
binaryVersion,
|
||||
buildTime,
|
||||
goVersion,
|
||||
gitCommit,
|
||||
)
|
||||
err = executor.Execute(exe, args)
|
||||
case commandWhoami:
|
||||
exe := executor.NewWhoAmIExecutor(topLevelFlags, commandWhoami, commandSummaries[commandWhoami])
|
||||
err = executor.Execute(exe, args)
|
||||
default:
|
||||
flag.Usage()
|
||||
|
||||
return unknownSubcommandError{command}
|
||||
return unknownCommandError{command}
|
||||
}
|
||||
|
||||
// To Do: create a function in executor package that will take in concrete type
|
||||
// as interface and run the parse and execute command.
|
||||
|
||||
if err := executor.Parse(args); err != nil {
|
||||
return fmt.Errorf("unable to parse the command line flags; %w", err)
|
||||
}
|
||||
|
||||
if err := executor.Execute(); err != nil {
|
||||
return fmt.Errorf("received an error after executing %q; %w", executor.Name(), err)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error executing the command; %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func usageFunc(summaries map[string]string) func() {
|
||||
cmds := make([]string, len(summaries))
|
||||
ind := 0
|
||||
|
||||
for k := range summaries {
|
||||
cmds[ind] = k
|
||||
ind++
|
||||
}
|
||||
|
||||
slices.Sort(cmds)
|
||||
|
||||
return func() {
|
||||
var builder strings.Builder
|
||||
|
||||
builder.WriteString("SUMMARY:\n enbas - A GoToSocial client for the terminal.\n\n")
|
||||
|
||||
if binaryVersion != "" {
|
||||
builder.WriteString("VERSION:\n " + binaryVersion + "\n\n")
|
||||
}
|
||||
|
||||
builder.WriteString("USAGE:\n enbas [flags]\n enbas [command]\n\nCOMMANDS:")
|
||||
|
||||
for _, cmd := range cmds {
|
||||
fmt.Fprintf(&builder, "\n %s\t%s", cmd, summaries[cmd])
|
||||
}
|
||||
|
||||
builder.WriteString("\n\nFLAGS:\n --help\n print the help message\n")
|
||||
flag.VisitAll(func(f *flag.Flag) {
|
||||
fmt.Fprintf(&builder, "\n --%s\n %s\n", f.Name, f.Usage)
|
||||
})
|
||||
|
||||
builder.WriteString("\nUse \"enbas [command] --help\" for more information about a command.\n")
|
||||
|
||||
w := flag.CommandLine.Output()
|
||||
fmt.Fprint(w, builder.String())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type removeCommand struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
resourceType string
|
||||
fromResourceType string
|
||||
listID string
|
||||
accountNames accountNames
|
||||
}
|
||||
|
||||
func newRemoveCommand(tlf topLevelFlags, name, summary string) *removeCommand {
|
||||
emptyArr := make([]string, 0, 3)
|
||||
|
||||
command := removeCommand{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
accountNames: accountNames(emptyArr),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
command.StringVar(&command.resourceType, flagType, "", "specify the resource type to remove (e.g. account, note)")
|
||||
command.StringVar(&command.fromResourceType, flagFrom, "", "specify the resource type to remove from (e.g. list, account, etc)")
|
||||
command.StringVar(&command.listID, flagListID, "", "the ID of the list to remove from")
|
||||
command.Var(&command.accountNames, flagAccountName, "the name of the account to remove from the resource")
|
||||
|
||||
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
func (c *removeCommand) Execute() error {
|
||||
if c.fromResourceType == "" {
|
||||
return flagNotSetError{flagText: flagFrom}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceList: c.removeFromList,
|
||||
resourceAccount: c.removeFromAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.fromResourceType]
|
||||
if !ok {
|
||||
return unsupportedResourceTypeError{resourceType: c.fromResourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *removeCommand) removeFromList(gtsClient *client.Client) error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceAccount: c.removeAccountsFromList,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedRemoveOperationError{
|
||||
ResourceType: c.resourceType,
|
||||
RemoveFromResourceType: c.fromResourceType,
|
||||
}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *removeCommand) removeAccountsFromList(gtsClient *client.Client) error {
|
||||
if c.listID == "" {
|
||||
return flagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
if len(c.accountNames) == 0 {
|
||||
return noAccountSpecifiedError{}
|
||||
}
|
||||
|
||||
accountIDs := make([]string, len(c.accountNames))
|
||||
|
||||
for i := range c.accountNames {
|
||||
accountID, err := getTheirAccountID(gtsClient, c.accountNames[i])
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get the account ID for %s, %w", c.accountNames[i], err)
|
||||
}
|
||||
|
||||
accountIDs[i] = accountID
|
||||
}
|
||||
|
||||
if err := gtsClient.RemoveAccountsFromList(c.listID, accountIDs); err != nil {
|
||||
return fmt.Errorf("unable to remove the accounts from the list; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully removed the account(s) from the list.")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *removeCommand) removeFromAccount(gtsClient *client.Client) error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceNote: c.removeNoteFromAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedRemoveOperationError{
|
||||
ResourceType: c.resourceType,
|
||||
RemoveFromResourceType: c.fromResourceType,
|
||||
}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *removeCommand) removeNoteFromAccount(gtsClient *client.Client) error {
|
||||
if len(c.accountNames) != 1 {
|
||||
return fmt.Errorf("unexpected number of accounts specified; want 1, got %d", len(c.accountNames))
|
||||
}
|
||||
|
||||
accountID, err := getAccountID(gtsClient, false, c.accountNames[0], c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
||||
if err := gtsClient.SetPrivateNote(accountID, ""); err != nil {
|
||||
return fmt.Errorf("unable to remove the private note from the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully removed the private note from the account.")
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
||||
)
|
||||
|
||||
type switchCommand struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
toAccount string
|
||||
}
|
||||
|
||||
func newSwitchCommand(tlf topLevelFlags, name, summary string) *switchCommand {
|
||||
command := switchCommand{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
command.StringVar(&command.toAccount, flagTo, "", "the account to switch to")
|
||||
|
||||
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
func (c *switchCommand) Execute() error {
|
||||
if c.toAccount == "" {
|
||||
return flagNotSetError{flagText: flagTo}
|
||||
}
|
||||
|
||||
if err := config.UpdateCurrentAccount(c.toAccount, c.topLevelFlags.configDir); err != nil {
|
||||
return fmt.Errorf("unable to switch accounts; %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("The current account is now set to %q.\n", c.toAccount)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||
)
|
||||
|
||||
type updateCommand struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
resourceType string
|
||||
listID string
|
||||
listTitle string
|
||||
listRepliesPolicy string
|
||||
}
|
||||
|
||||
func newUpdateCommand(tlf topLevelFlags, name, summary string) *updateCommand {
|
||||
command := updateCommand{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
command.StringVar(&command.resourceType, flagType, "", "specify the type of resource to update")
|
||||
command.StringVar(&command.listID, flagListID, "", "specify the ID of the list to update")
|
||||
command.StringVar(&command.listTitle, flagListTitle, "", "specify the title of the list")
|
||||
command.StringVar(&command.listRepliesPolicy, flagListRepliesPolicy, "", "specify the policy of the replies for this list (valid values are followed, list and none)")
|
||||
|
||||
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
func (c *updateCommand) Execute() error {
|
||||
if c.resourceType == "" {
|
||||
return flagNotSetError{flagText: flagType}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceList: c.updateList,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedResourceTypeError{resourceType: c.resourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *updateCommand) updateList(gtsClient *client.Client) error {
|
||||
if c.listID == "" {
|
||||
return flagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
list, err := gtsClient.GetList(c.listID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get the list; %w", err)
|
||||
}
|
||||
|
||||
if c.listTitle != "" {
|
||||
list.Title = c.listTitle
|
||||
}
|
||||
|
||||
if c.listRepliesPolicy != "" {
|
||||
repliesPolicy, err := model.ParseListRepliesPolicy(c.listRepliesPolicy)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse the list replies policy; %w", err)
|
||||
}
|
||||
|
||||
list.RepliesPolicy = repliesPolicy
|
||||
}
|
||||
|
||||
updatedList, err := gtsClient.UpdateList(list)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to update the list; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully updated the list.")
|
||||
fmt.Println(updatedList)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func commandUsageFunc(name, summary string, flagset *flag.FlagSet) func() {
|
||||
return func() {
|
||||
var builder strings.Builder
|
||||
|
||||
fmt.Fprintf(
|
||||
&builder,
|
||||
"SUMMARY:\n %s - %s\n\nUSAGE:\n enbas %s [flags]\n\nFLAGS:",
|
||||
name,
|
||||
summary,
|
||||
name,
|
||||
)
|
||||
|
||||
flagset.VisitAll(func(f *flag.Flag) {
|
||||
fmt.Fprintf(
|
||||
&builder,
|
||||
"\n --%s\n %s",
|
||||
f.Name,
|
||||
f.Usage,
|
||||
)
|
||||
})
|
||||
|
||||
builder.WriteString("\n")
|
||||
|
||||
w := flag.CommandLine.Output()
|
||||
|
||||
fmt.Fprint(w, builder.String())
|
||||
}
|
||||
}
|
||||
|
||||
func enbasUsageFunc(summaries map[string]string) func() {
|
||||
cmds := make([]string, len(summaries))
|
||||
ind := 0
|
||||
|
||||
for k := range summaries {
|
||||
cmds[ind] = k
|
||||
ind++
|
||||
}
|
||||
|
||||
slices.Sort(cmds)
|
||||
|
||||
return func() {
|
||||
var builder strings.Builder
|
||||
|
||||
builder.WriteString("SUMMARY:\n enbas - A GoToSocial client for the terminal.\n\n")
|
||||
|
||||
if binaryVersion != "" {
|
||||
builder.WriteString("VERSION:\n " + binaryVersion + "\n\n")
|
||||
}
|
||||
|
||||
builder.WriteString("USAGE:\n enbas [flags]\n enbas [command]\n\nCOMMANDS:")
|
||||
|
||||
for _, cmd := range cmds {
|
||||
fmt.Fprintf(&builder, "\n %s\t%s", cmd, summaries[cmd])
|
||||
}
|
||||
|
||||
builder.WriteString("\n\nFLAGS:\n --help\n print the help message\n")
|
||||
flag.VisitAll(func(f *flag.Flag) {
|
||||
fmt.Fprintf(&builder, "\n --%s\n %s\n", f.Name, f.Usage)
|
||||
})
|
||||
|
||||
builder.WriteString("\nUse \"enbas [command] --help\" for more information about a command.\n")
|
||||
|
||||
w := flag.CommandLine.Output()
|
||||
fmt.Fprint(w, builder.String())
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
||||
)
|
||||
|
||||
type whoAmICommand struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
}
|
||||
|
||||
func newWhoAmICommand(tlf topLevelFlags, name, summary string) *whoAmICommand {
|
||||
command := whoAmICommand{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
func (c *whoAmICommand) Execute() error {
|
||||
config, err := config.NewCredentialsConfigFromFile(c.topLevelFlags.configDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to load the credential config; %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("You are %s\n", config.CurrentAccount)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package executor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -26,7 +26,7 @@ func getAccountID(gtsClient *client.Client, myAccount bool, accountName, configD
|
|||
return "", fmt.Errorf("unable to get their account ID; %w", err)
|
||||
}
|
||||
default:
|
||||
return "", noAccountSpecifiedError{}
|
||||
return "", NoAccountSpecifiedError{}
|
||||
}
|
||||
|
||||
return accountID, nil
|
146
internal/executor/add.go
Normal file
146
internal/executor/add.go
Normal file
|
@ -0,0 +1,146 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type AddExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags TopLevelFlags
|
||||
resourceType string
|
||||
toResourceType string
|
||||
listID string
|
||||
accountNames AccountNames
|
||||
content string
|
||||
}
|
||||
|
||||
func NewAddExecutor(tlf TopLevelFlags, name, summary string) *AddExecutor {
|
||||
emptyArr := make([]string, 0, 3)
|
||||
|
||||
addExe := AddExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
accountNames: AccountNames(emptyArr),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
addExe.StringVar(&addExe.resourceType, flagType, "", "specify the resource type to add (e.g. account, note)")
|
||||
addExe.StringVar(&addExe.toResourceType, flagTo, "", "specify the target resource type to add to (e.g. list, account, etc)")
|
||||
addExe.StringVar(&addExe.listID, flagListID, "", "the ID of the list to add to")
|
||||
addExe.Var(&addExe.accountNames, flagAccountName, "the name of the account to add to the resource")
|
||||
addExe.StringVar(&addExe.content, flagContent, "", "the content of the note")
|
||||
|
||||
addExe.Usage = commandUsageFunc(name, summary, addExe.FlagSet)
|
||||
|
||||
return &addExe
|
||||
}
|
||||
|
||||
func (a *AddExecutor) Execute() error {
|
||||
if a.toResourceType == "" {
|
||||
return FlagNotSetError{flagText: flagTo}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceList: a.addToList,
|
||||
resourceAccount: a.addToAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[a.toResourceType]
|
||||
if !ok {
|
||||
return UnsupportedTypeError{resourceType: a.toResourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(a.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (a *AddExecutor) addToList(gtsClient *client.Client) error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceAccount: a.addAccountsToList,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[a.resourceType]
|
||||
if !ok {
|
||||
return UnsupportedAddOperationError{
|
||||
ResourceType: a.resourceType,
|
||||
AddToResourceType: a.toResourceType,
|
||||
}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (a *AddExecutor) addAccountsToList(gtsClient *client.Client) error {
|
||||
if a.listID == "" {
|
||||
return FlagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
if len(a.accountNames) == 0 {
|
||||
return NoAccountSpecifiedError{}
|
||||
}
|
||||
|
||||
accountIDs := make([]string, len(a.accountNames))
|
||||
|
||||
for ind := range a.accountNames {
|
||||
accountID, err := getTheirAccountID(gtsClient, a.accountNames[ind])
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get the account ID for %s, %w", a.accountNames[ind], err)
|
||||
}
|
||||
|
||||
accountIDs[ind] = accountID
|
||||
}
|
||||
|
||||
if err := gtsClient.AddAccountsToList(a.listID, accountIDs); err != nil {
|
||||
return fmt.Errorf("unable to add the accounts to the list; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully added the account(s) to the list.")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AddExecutor) addToAccount(gtsClient *client.Client) error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceNote: a.addNoteToAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[a.resourceType]
|
||||
if !ok {
|
||||
return UnsupportedAddOperationError{
|
||||
ResourceType: a.resourceType,
|
||||
AddToResourceType: a.toResourceType,
|
||||
}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (a *AddExecutor) addNoteToAccount(gtsClient *client.Client) error {
|
||||
if len(a.accountNames) != 1 {
|
||||
return fmt.Errorf("unexpected number of accounts specified; want 1, got %d", len(a.accountNames))
|
||||
}
|
||||
|
||||
accountID, err := getAccountID(gtsClient, false, a.accountNames[0], a.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
||||
if a.content == "" {
|
||||
return EmptyContentError{}
|
||||
}
|
||||
|
||||
if err := gtsClient.SetPrivateNote(accountID, a.content); err != nil {
|
||||
return fmt.Errorf("unable to add the private note to the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully added the private note to the account.")
|
||||
|
||||
return nil
|
||||
}
|
80
internal/executor/block.go
Normal file
80
internal/executor/block.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type BlockExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags TopLevelFlags
|
||||
resourceType string
|
||||
accountName string
|
||||
unblock bool
|
||||
}
|
||||
|
||||
func NewBlockExecutor(tlf TopLevelFlags, name, summary string, unblock bool) *BlockExecutor {
|
||||
blockExe := BlockExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
|
||||
topLevelFlags: tlf,
|
||||
unblock: unblock,
|
||||
}
|
||||
|
||||
blockExe.StringVar(&blockExe.resourceType, flagType, "", "specify the type of resource to block or unblock")
|
||||
blockExe.StringVar(&blockExe.accountName, flagAccountName, "", "specify the account name in full (username@domain)")
|
||||
|
||||
blockExe.Usage = commandUsageFunc(name, summary, blockExe.FlagSet)
|
||||
|
||||
return &blockExe
|
||||
}
|
||||
|
||||
func (b *BlockExecutor) Execute() error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceAccount: b.blockAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[b.resourceType]
|
||||
if !ok {
|
||||
return UnsupportedTypeError{resourceType: b.resourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(b.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (b *BlockExecutor) blockAccount(gtsClient *client.Client) error {
|
||||
accountID, err := getAccountID(gtsClient, false, b.accountName, b.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
||||
if b.unblock {
|
||||
return b.unblockAccount(gtsClient, accountID)
|
||||
}
|
||||
|
||||
if err := gtsClient.BlockAccount(accountID); err != nil {
|
||||
return fmt.Errorf("unable to block the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully blocked the account.")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BlockExecutor) unblockAccount(gtsClient *client.Client, accountID string) error {
|
||||
if err := gtsClient.UnblockAccount(accountID); err != nil {
|
||||
return fmt.Errorf("unable to unblock the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully unblocked the account.")
|
||||
|
||||
return nil
|
||||
}
|
32
internal/executor/const.go
Normal file
32
internal/executor/const.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package executor
|
||||
|
||||
const (
|
||||
flagAccountName = "account-name"
|
||||
flagContent = "content"
|
||||
flagInstance = "instance"
|
||||
flagLimit = "limit"
|
||||
flagListID = "list-id"
|
||||
flagListTitle = "list-title"
|
||||
flagListRepliesPolicy = "list-replies-policy"
|
||||
flagMyAccount = "my-account"
|
||||
flagNotify = "notify"
|
||||
flagFrom = "from"
|
||||
flagType = "type"
|
||||
flagShowRelationship = "show-relationship"
|
||||
flagShowPreferences = "show-preferences"
|
||||
flagShowReposts = "show-reposts"
|
||||
flagStatusID = "status-id"
|
||||
flagTag = "tag"
|
||||
flagTimelineCategory = "timeline-category"
|
||||
flagTo = "to"
|
||||
|
||||
resourceAccount = "account"
|
||||
resourceBlocked = "blocked"
|
||||
resourceFollowers = "followers"
|
||||
resourceFollowing = "following"
|
||||
resourceInstance = "instance"
|
||||
resourceList = "list"
|
||||
resourceNote = "note"
|
||||
resourceStatus = "status"
|
||||
resourceTimeline = "timeline"
|
||||
)
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
@ -8,37 +8,37 @@ import (
|
|||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||
)
|
||||
|
||||
type createCommand struct {
|
||||
type CreateExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
topLevelFlags TopLevelFlags
|
||||
resourceType string
|
||||
listTitle string
|
||||
listRepliesPolicy string
|
||||
}
|
||||
|
||||
func newCreateCommand(tlf topLevelFlags, name, summary string) *createCommand {
|
||||
command := createCommand{
|
||||
func NewCreateExecutor(tlf TopLevelFlags, name, summary string) *CreateExecutor {
|
||||
createExe := CreateExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
command.StringVar(&command.resourceType, flagType, "", "specify the type of resource to create")
|
||||
command.StringVar(&command.listTitle, flagListTitle, "", "specify the title of the list")
|
||||
command.StringVar(&command.listRepliesPolicy, flagListRepliesPolicy, "list", "specify the policy of the replies for this list (valid values are followed, list and none)")
|
||||
createExe.StringVar(&createExe.resourceType, flagType, "", "specify the type of resource to create")
|
||||
createExe.StringVar(&createExe.listTitle, flagListTitle, "", "specify the title of the list")
|
||||
createExe.StringVar(&createExe.listRepliesPolicy, flagListRepliesPolicy, "list", "specify the policy of the replies for this list (valid values are followed, list and none)")
|
||||
|
||||
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
||||
createExe.Usage = commandUsageFunc(name, summary, createExe.FlagSet)
|
||||
|
||||
return &command
|
||||
return &createExe
|
||||
}
|
||||
|
||||
func (c *createCommand) Execute() error {
|
||||
func (c *CreateExecutor) Execute() error {
|
||||
if c.resourceType == "" {
|
||||
return flagNotSetError{flagText: flagType}
|
||||
return FlagNotSetError{flagText: flagType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.configDir)
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
@ -49,15 +49,15 @@ func (c *createCommand) Execute() error {
|
|||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedResourceTypeError{resourceType: c.resourceType}
|
||||
return UnsupportedTypeError{resourceType: c.resourceType}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *createCommand) createList(gtsClient *client.Client) error {
|
||||
func (c *CreateExecutor) createList(gtsClient *client.Client) error {
|
||||
if c.listTitle == "" {
|
||||
return flagNotSetError{flagText: flagListTitle}
|
||||
return FlagNotSetError{flagText: flagListTitle}
|
||||
}
|
||||
|
||||
repliesPolicy, err := model.ParseListRepliesPolicy(c.listRepliesPolicy)
|
66
internal/executor/delete.go
Normal file
66
internal/executor/delete.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type DeleteExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags TopLevelFlags
|
||||
resourceType string
|
||||
listID string
|
||||
}
|
||||
|
||||
func NewDeleteExecutor(tlf TopLevelFlags, name, summary string) *DeleteExecutor {
|
||||
deleteExe := DeleteExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
deleteExe.StringVar(&deleteExe.resourceType, flagType, "", "specify the type of resource to delete")
|
||||
deleteExe.StringVar(&deleteExe.listID, flagListID, "", "specify the ID of the list to delete")
|
||||
|
||||
deleteExe.Usage = commandUsageFunc(name, summary, deleteExe.FlagSet)
|
||||
|
||||
return &deleteExe
|
||||
}
|
||||
|
||||
func (d *DeleteExecutor) Execute() error {
|
||||
if d.resourceType == "" {
|
||||
return FlagNotSetError{flagText: flagType}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceList: d.deleteList,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[d.resourceType]
|
||||
if !ok {
|
||||
return UnsupportedTypeError{resourceType: d.resourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(d.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (d *DeleteExecutor) deleteList(gtsClient *client.Client) error {
|
||||
if d.listID == "" {
|
||||
return FlagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
if err := gtsClient.DeleteList(d.listID); err != nil {
|
||||
return fmt.Errorf("unable to delete the list; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("The list was successfully deleted.")
|
||||
|
||||
return nil
|
||||
}
|
55
internal/executor/errors.go
Normal file
55
internal/executor/errors.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package executor
|
||||
|
||||
type FlagNotSetError struct {
|
||||
flagText string
|
||||
}
|
||||
|
||||
func (e FlagNotSetError) Error() string {
|
||||
return "the flag '" + e.flagText + "' is not set"
|
||||
}
|
||||
|
||||
type UnsupportedTypeError struct {
|
||||
resourceType string
|
||||
}
|
||||
|
||||
func (e UnsupportedTypeError) Error() string {
|
||||
return "unsupported resource type '" + e.resourceType + "'"
|
||||
}
|
||||
|
||||
type InvalidTimelineCategoryError struct {
|
||||
category string
|
||||
}
|
||||
|
||||
func (e InvalidTimelineCategoryError) Error() string {
|
||||
return "'" + e.category + "' is not a valid timeline category (please choose home, public, tag or list)"
|
||||
}
|
||||
|
||||
type NoAccountSpecifiedError struct{}
|
||||
|
||||
func (e NoAccountSpecifiedError) Error() string {
|
||||
return "no account specified in this request"
|
||||
}
|
||||
|
||||
type UnsupportedAddOperationError struct {
|
||||
ResourceType string
|
||||
AddToResourceType string
|
||||
}
|
||||
|
||||
func (e UnsupportedAddOperationError) Error() string {
|
||||
return "adding '" + e.ResourceType + "' to '" + e.AddToResourceType + "' is not supported"
|
||||
}
|
||||
|
||||
type UnsupportedRemoveOperationError struct {
|
||||
ResourceType string
|
||||
RemoveFromResourceType string
|
||||
}
|
||||
|
||||
func (e UnsupportedRemoveOperationError) Error() string {
|
||||
return "removing '" + e.ResourceType + "' from '" + e.RemoveFromResourceType + "' is not supported"
|
||||
}
|
||||
|
||||
type EmptyContentError struct{}
|
||||
|
||||
func (e EmptyContentError) Error() string {
|
||||
return "content should not be empty"
|
||||
}
|
21
internal/executor/executor.go
Normal file
21
internal/executor/executor.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package executor
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Executor interface {
|
||||
Name() string
|
||||
Parse(args []string) error
|
||||
Execute() error
|
||||
}
|
||||
|
||||
func Execute(executor Executor, args []string) error {
|
||||
if err := executor.Parse(args); err != nil {
|
||||
return fmt.Errorf("unable to parse the command line flags; %w", err)
|
||||
}
|
||||
|
||||
if err := executor.Execute(); err != nil {
|
||||
return fmt.Errorf("unable to execute the command %q; %w", executor.Name(), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
21
internal/executor/flags.go
Normal file
21
internal/executor/flags.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package executor
|
||||
|
||||
import "strings"
|
||||
|
||||
type AccountNames []string
|
||||
|
||||
func (a *AccountNames) String() string {
|
||||
return strings.Join(*a, ", ")
|
||||
}
|
||||
|
||||
func (a *AccountNames) Set(value string) error {
|
||||
if len(value) > 0 {
|
||||
*a = append(*a, value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type TopLevelFlags struct {
|
||||
ConfigDir string
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
@ -7,10 +7,10 @@ import (
|
|||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type followCommand struct {
|
||||
type FollowExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
topLevelFlags TopLevelFlags
|
||||
resourceType string
|
||||
accountName string
|
||||
showReposts bool
|
||||
|
@ -18,8 +18,8 @@ type followCommand struct {
|
|||
unfollow bool
|
||||
}
|
||||
|
||||
func newFollowCommand(tlf topLevelFlags, name, summary string, unfollow bool) *followCommand {
|
||||
command := followCommand{
|
||||
func NewFollowExecutor(tlf TopLevelFlags, name, summary string, unfollow bool) *FollowExecutor {
|
||||
command := FollowExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
unfollow: unfollow,
|
||||
topLevelFlags: tlf,
|
||||
|
@ -35,17 +35,17 @@ func newFollowCommand(tlf topLevelFlags, name, summary string, unfollow bool) *f
|
|||
return &command
|
||||
}
|
||||
|
||||
func (c *followCommand) Execute() error {
|
||||
func (c *FollowExecutor) Execute() error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceAccount: c.followAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedResourceTypeError{resourceType: c.resourceType}
|
||||
return UnsupportedTypeError{resourceType: c.resourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.configDir)
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ func (c *followCommand) Execute() error {
|
|||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *followCommand) followAccount(gtsClient *client.Client) error {
|
||||
accountID, err := getAccountID(gtsClient, false, c.accountName, c.topLevelFlags.configDir)
|
||||
func (c *FollowExecutor) followAccount(gtsClient *client.Client) error {
|
||||
accountID, err := getAccountID(gtsClient, false, c.accountName, c.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func (c *followCommand) followAccount(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *followCommand) unfollowAccount(gtsClient *client.Client, accountID string) error {
|
||||
func (c *FollowExecutor) unfollowAccount(gtsClient *client.Client, accountID string) error {
|
||||
if err := gtsClient.UnfollowAccount(accountID); err != nil {
|
||||
return fmt.Errorf("unable to unfollow the account; %w", err)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
@ -10,15 +10,15 @@ import (
|
|||
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
||||
)
|
||||
|
||||
type loginCommand struct {
|
||||
type LoginExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags topLevelFlags
|
||||
topLevelFlags TopLevelFlags
|
||||
instance string
|
||||
}
|
||||
|
||||
func newLoginCommand(tlf topLevelFlags, name, summary string) *loginCommand {
|
||||
command := loginCommand{
|
||||
func NewLoginExecutor(tlf TopLevelFlags, name, summary string) *LoginExecutor {
|
||||
command := LoginExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
instance: "",
|
||||
|
@ -31,11 +31,11 @@ func newLoginCommand(tlf topLevelFlags, name, summary string) *loginCommand {
|
|||
return &command
|
||||
}
|
||||
|
||||
func (c *loginCommand) Execute() error {
|
||||
func (c *LoginExecutor) Execute() error {
|
||||
var err error
|
||||
|
||||
if c.instance == "" {
|
||||
return flagNotSetError{flagText: flagInstance}
|
||||
return FlagNotSetError{flagText: flagInstance}
|
||||
}
|
||||
|
||||
instance := c.instance
|
||||
|
@ -91,7 +91,7 @@ Once you have the code please copy and paste it below.
|
|||
return fmt.Errorf("unable to verify the credentials; %w", err)
|
||||
}
|
||||
|
||||
loginName, err := config.SaveCredentials(c.topLevelFlags.configDir, account.Username, gtsClient.Authentication)
|
||||
loginName, err := config.SaveCredentials(c.topLevelFlags.ConfigDir, account.Username, gtsClient.Authentication)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to save the authentication details; %w", err)
|
||||
}
|
140
internal/executor/remove.go
Normal file
140
internal/executor/remove.go
Normal file
|
@ -0,0 +1,140 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
)
|
||||
|
||||
type RemoveExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags TopLevelFlags
|
||||
resourceType string
|
||||
fromResourceType string
|
||||
listID string
|
||||
accountNames AccountNames
|
||||
}
|
||||
|
||||
func NewRemoveExecutor(tlf TopLevelFlags, name, summary string) *RemoveExecutor {
|
||||
emptyArr := make([]string, 0, 3)
|
||||
|
||||
removeExe := RemoveExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
accountNames: AccountNames(emptyArr),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
removeExe.StringVar(&removeExe.resourceType, flagType, "", "specify the resource type to remove (e.g. account, note)")
|
||||
removeExe.StringVar(&removeExe.fromResourceType, flagFrom, "", "specify the resource type to remove from (e.g. list, account, etc)")
|
||||
removeExe.StringVar(&removeExe.listID, flagListID, "", "the ID of the list to remove from")
|
||||
removeExe.Var(&removeExe.accountNames, flagAccountName, "the name of the account to remove from the resource")
|
||||
|
||||
removeExe.Usage = commandUsageFunc(name, summary, removeExe.FlagSet)
|
||||
|
||||
return &removeExe
|
||||
}
|
||||
|
||||
func (r *RemoveExecutor) Execute() error {
|
||||
if r.fromResourceType == "" {
|
||||
return FlagNotSetError{flagText: flagFrom}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceList: r.removeFromList,
|
||||
resourceAccount: r.removeFromAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[r.fromResourceType]
|
||||
if !ok {
|
||||
return UnsupportedTypeError{resourceType: r.fromResourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(r.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (r *RemoveExecutor) removeFromList(gtsClient *client.Client) error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceAccount: r.removeAccountsFromList,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[r.resourceType]
|
||||
if !ok {
|
||||
return UnsupportedRemoveOperationError{
|
||||
ResourceType: r.resourceType,
|
||||
RemoveFromResourceType: r.fromResourceType,
|
||||
}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (r *RemoveExecutor) removeAccountsFromList(gtsClient *client.Client) error {
|
||||
if r.listID == "" {
|
||||
return FlagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
if len(r.accountNames) == 0 {
|
||||
return NoAccountSpecifiedError{}
|
||||
}
|
||||
|
||||
accountIDs := make([]string, len(r.accountNames))
|
||||
|
||||
for i := range r.accountNames {
|
||||
accountID, err := getTheirAccountID(gtsClient, r.accountNames[i])
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get the account ID for %s, %w", r.accountNames[i], err)
|
||||
}
|
||||
|
||||
accountIDs[i] = accountID
|
||||
}
|
||||
|
||||
if err := gtsClient.RemoveAccountsFromList(r.listID, accountIDs); err != nil {
|
||||
return fmt.Errorf("unable to remove the accounts from the list; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully removed the account(s) from the list.")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RemoveExecutor) removeFromAccount(gtsClient *client.Client) error {
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceNote: r.removeNoteFromAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[r.resourceType]
|
||||
if !ok {
|
||||
return UnsupportedRemoveOperationError{
|
||||
ResourceType: r.resourceType,
|
||||
RemoveFromResourceType: r.fromResourceType,
|
||||
}
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (r *RemoveExecutor) removeNoteFromAccount(gtsClient *client.Client) error {
|
||||
if len(r.accountNames) != 1 {
|
||||
return fmt.Errorf("unexpected number of accounts specified; want 1, got %d", len(r.accountNames))
|
||||
}
|
||||
|
||||
accountID, err := getAccountID(gtsClient, false, r.accountNames[0], r.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
||||
if err := gtsClient.SetPrivateNote(accountID, ""); err != nil {
|
||||
return fmt.Errorf("unable to remove the private note from the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully removed the private note from the account.")
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
@ -9,9 +9,9 @@ import (
|
|||
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
||||
)
|
||||
|
||||
type showCommand struct {
|
||||
type ShowExecutor struct {
|
||||
*flag.FlagSet
|
||||
topLevelFlags topLevelFlags
|
||||
topLevelFlags TopLevelFlags
|
||||
myAccount bool
|
||||
showAccountRelationship bool
|
||||
showUserPreferences bool
|
||||
|
@ -24,8 +24,8 @@ type showCommand struct {
|
|||
limit int
|
||||
}
|
||||
|
||||
func newShowCommand(tlf topLevelFlags, name, summary string) *showCommand {
|
||||
command := showCommand{
|
||||
func NewShowExecutor(tlf TopLevelFlags, name, summary string) *ShowExecutor {
|
||||
command := ShowExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
@ -46,9 +46,9 @@ func newShowCommand(tlf topLevelFlags, name, summary string) *showCommand {
|
|||
return &command
|
||||
}
|
||||
|
||||
func (c *showCommand) Execute() error {
|
||||
func (c *ShowExecutor) Execute() error {
|
||||
if c.resourceType == "" {
|
||||
return flagNotSetError{flagText: flagType}
|
||||
return FlagNotSetError{flagText: flagType}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
|
@ -64,10 +64,10 @@ func (c *showCommand) Execute() error {
|
|||
|
||||
doFunc, ok := funcMap[c.resourceType]
|
||||
if !ok {
|
||||
return unsupportedResourceTypeError{resourceType: c.resourceType}
|
||||
return UnsupportedTypeError{resourceType: c.resourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.configDir)
|
||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ func (c *showCommand) Execute() error {
|
|||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (c *showCommand) showInstance(gtsClient *client.Client) error {
|
||||
func (c *ShowExecutor) showInstance(gtsClient *client.Client) error {
|
||||
instance, err := gtsClient.GetInstance()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to retrieve the instance details; %w", err)
|
||||
|
@ -86,20 +86,20 @@ func (c *showCommand) showInstance(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *showCommand) showAccount(gtsClient *client.Client) error {
|
||||
func (c *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
||||
var (
|
||||
account model.Account
|
||||
err error
|
||||
)
|
||||
|
||||
if c.myAccount {
|
||||
account, err = getMyAccount(gtsClient, c.topLevelFlags.configDir)
|
||||
account, err = getMyAccount(gtsClient, c.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account details; %w", err)
|
||||
}
|
||||
} else {
|
||||
if c.accountName == "" {
|
||||
return flagNotSetError{flagText: flagAccountName}
|
||||
return FlagNotSetError{flagText: flagAccountName}
|
||||
}
|
||||
|
||||
account, err = getAccount(gtsClient, c.accountName)
|
||||
|
@ -131,9 +131,9 @@ func (c *showCommand) showAccount(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *showCommand) showStatus(gtsClient *client.Client) error {
|
||||
func (c *ShowExecutor) showStatus(gtsClient *client.Client) error {
|
||||
if c.statusID == "" {
|
||||
return flagNotSetError{flagText: flagStatusID}
|
||||
return FlagNotSetError{flagText: flagStatusID}
|
||||
}
|
||||
|
||||
status, err := gtsClient.GetStatus(c.statusID)
|
||||
|
@ -146,7 +146,7 @@ func (c *showCommand) showStatus(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *showCommand) showTimeline(gtsClient *client.Client) error {
|
||||
func (c *ShowExecutor) showTimeline(gtsClient *client.Client) error {
|
||||
var (
|
||||
timeline model.Timeline
|
||||
err error
|
||||
|
@ -159,18 +159,18 @@ func (c *showCommand) showTimeline(gtsClient *client.Client) error {
|
|||
timeline, err = gtsClient.GetPublicTimeline(c.limit)
|
||||
case "list":
|
||||
if c.listID == "" {
|
||||
return flagNotSetError{flagText: flagListID}
|
||||
return FlagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
timeline, err = gtsClient.GetListTimeline(c.listID, c.limit)
|
||||
case "tag":
|
||||
if c.tag == "" {
|
||||
return flagNotSetError{flagText: flagTag}
|
||||
return FlagNotSetError{flagText: flagTag}
|
||||
}
|
||||
|
||||
timeline, err = gtsClient.GetTagTimeline(c.tag, c.limit)
|
||||
default:
|
||||
return invalidTimelineCategoryError{category: c.timelineCategory}
|
||||
return InvalidTimelineCategoryError{category: c.timelineCategory}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -188,7 +188,7 @@ func (c *showCommand) showTimeline(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *showCommand) showList(gtsClient *client.Client) error {
|
||||
func (c *ShowExecutor) showList(gtsClient *client.Client) error {
|
||||
if c.listID == "" {
|
||||
return c.showLists(gtsClient)
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ func (c *showCommand) showList(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *showCommand) showLists(gtsClient *client.Client) error {
|
||||
func (c *ShowExecutor) showLists(gtsClient *client.Client) error {
|
||||
lists, err := gtsClient.GetAllLists()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to retrieve the lists; %w", err)
|
||||
|
@ -235,8 +235,8 @@ func (c *showCommand) showLists(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *showCommand) showFollowers(gtsClient *client.Client) error {
|
||||
accountID, err := getAccountID(gtsClient, c.myAccount, c.accountName, c.topLevelFlags.configDir)
|
||||
func (c *ShowExecutor) showFollowers(gtsClient *client.Client) error {
|
||||
accountID, err := getAccountID(gtsClient, c.myAccount, c.accountName, c.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
@ -255,8 +255,8 @@ func (c *showCommand) showFollowers(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *showCommand) showFollowing(gtsClient *client.Client) error {
|
||||
accountID, err := getAccountID(gtsClient, c.myAccount, c.accountName, c.topLevelFlags.configDir)
|
||||
func (c *ShowExecutor) showFollowing(gtsClient *client.Client) error {
|
||||
accountID, err := getAccountID(gtsClient, c.myAccount, c.accountName, c.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("received an error while getting the account ID; %w", err)
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ func (c *showCommand) showFollowing(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *showCommand) showBlocked(gtsClient *client.Client) error {
|
||||
func (c *ShowExecutor) showBlocked(gtsClient *client.Client) error {
|
||||
blocked, err := gtsClient.GetBlockedAccounts(c.limit)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to retrieve the list of blocked accounts; %w", err)
|
57
internal/executor/switch.go
Normal file
57
internal/executor/switch.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
||||
)
|
||||
|
||||
type SwitchExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags TopLevelFlags
|
||||
toResourceType string
|
||||
accountName string
|
||||
}
|
||||
|
||||
func NewSwitchExecutor(tlf TopLevelFlags, name, summary string) *SwitchExecutor {
|
||||
switchExe := SwitchExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
switchExe.StringVar(&switchExe.toResourceType, flagTo, "", "the account to switch to")
|
||||
switchExe.StringVar(&switchExe.accountName, flagAccountName, "", "the name of the account to switch to")
|
||||
|
||||
switchExe.Usage = commandUsageFunc(name, summary, switchExe.FlagSet)
|
||||
|
||||
return &switchExe
|
||||
}
|
||||
|
||||
func (s *SwitchExecutor) Execute() error {
|
||||
funcMap := map[string]func() error{
|
||||
resourceAccount: s.switchToAccount,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[s.toResourceType]
|
||||
if !ok {
|
||||
return UnsupportedTypeError{resourceType: s.toResourceType}
|
||||
}
|
||||
|
||||
return doFunc()
|
||||
}
|
||||
|
||||
func (s *SwitchExecutor) switchToAccount() error {
|
||||
if s.accountName == "" {
|
||||
return NoAccountSpecifiedError{}
|
||||
}
|
||||
|
||||
if err := config.UpdateCurrentAccount(s.accountName, s.topLevelFlags.ConfigDir); err != nil {
|
||||
return fmt.Errorf("unable to switch account to the account; %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("The current account is now set to %q.\n", s.accountName)
|
||||
|
||||
return nil
|
||||
}
|
91
internal/executor/update.go
Normal file
91
internal/executor/update.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||
)
|
||||
|
||||
type EditExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags TopLevelFlags
|
||||
resourceType string
|
||||
listID string
|
||||
listTitle string
|
||||
listRepliesPolicy string
|
||||
}
|
||||
|
||||
func NewEditExecutor(tlf TopLevelFlags, name, summary string) *EditExecutor {
|
||||
editExe := EditExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
editExe.StringVar(&editExe.resourceType, flagType, "", "specify the type of resource to update")
|
||||
editExe.StringVar(&editExe.listID, flagListID, "", "specify the ID of the list to update")
|
||||
editExe.StringVar(&editExe.listTitle, flagListTitle, "", "specify the title of the list")
|
||||
editExe.StringVar(&editExe.listRepliesPolicy, flagListRepliesPolicy, "", "specify the policy of the replies for this list (valid values are followed, list and none)")
|
||||
|
||||
editExe.Usage = commandUsageFunc(name, summary, editExe.FlagSet)
|
||||
|
||||
return &editExe
|
||||
}
|
||||
|
||||
func (e *EditExecutor) Execute() error {
|
||||
if e.resourceType == "" {
|
||||
return FlagNotSetError{flagText: flagType}
|
||||
}
|
||||
|
||||
funcMap := map[string]func(*client.Client) error{
|
||||
resourceList: e.updateList,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[e.resourceType]
|
||||
if !ok {
|
||||
return UnsupportedTypeError{resourceType: e.resourceType}
|
||||
}
|
||||
|
||||
gtsClient, err := client.NewClientFromConfig(e.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
||||
}
|
||||
|
||||
return doFunc(gtsClient)
|
||||
}
|
||||
|
||||
func (e *EditExecutor) updateList(gtsClient *client.Client) error {
|
||||
if e.listID == "" {
|
||||
return FlagNotSetError{flagText: flagListID}
|
||||
}
|
||||
|
||||
list, err := gtsClient.GetList(e.listID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get the list; %w", err)
|
||||
}
|
||||
|
||||
if e.listTitle != "" {
|
||||
list.Title = e.listTitle
|
||||
}
|
||||
|
||||
if e.listRepliesPolicy != "" {
|
||||
repliesPolicy, err := model.ParseListRepliesPolicy(e.listRepliesPolicy)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse the list replies policy; %w", err)
|
||||
}
|
||||
|
||||
list.RepliesPolicy = repliesPolicy
|
||||
}
|
||||
|
||||
updatedList, err := gtsClient.UpdateList(list)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to update the list; %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully updated the list.")
|
||||
fmt.Println(updatedList)
|
||||
|
||||
return nil
|
||||
}
|
37
internal/executor/usage.go
Normal file
37
internal/executor/usage.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// commandUsageFunc returns the function used to print a command's help page.
|
||||
func commandUsageFunc(name, summary string, flagset *flag.FlagSet) func() {
|
||||
return func() {
|
||||
var builder strings.Builder
|
||||
|
||||
fmt.Fprintf(
|
||||
&builder,
|
||||
"SUMMARY:\n %s - %s\n\nUSAGE:\n enbas %s [flags]\n\nFLAGS:",
|
||||
name,
|
||||
summary,
|
||||
name,
|
||||
)
|
||||
|
||||
flagset.VisitAll(func(f *flag.Flag) {
|
||||
fmt.Fprintf(
|
||||
&builder,
|
||||
"\n --%s\n %s",
|
||||
f.Name,
|
||||
f.Usage,
|
||||
)
|
||||
})
|
||||
|
||||
builder.WriteString("\n")
|
||||
|
||||
w := flag.CommandLine.Output()
|
||||
|
||||
fmt.Fprint(w, builder.String())
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
@ -7,14 +7,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
binaryVersion string
|
||||
buildTime string
|
||||
goVersion string
|
||||
gitCommit string
|
||||
)
|
||||
|
||||
type versionCommand struct {
|
||||
type VersionExecutor struct {
|
||||
*flag.FlagSet
|
||||
showFullVersion bool
|
||||
binaryVersion string
|
||||
|
@ -23,8 +16,8 @@ type versionCommand struct {
|
|||
gitCommit string
|
||||
}
|
||||
|
||||
func newVersionCommand(name, summary string) *versionCommand {
|
||||
command := versionCommand{
|
||||
func NewVersionExecutor(name, summary, binaryVersion, buildTime, goVersion, gitCommit string) *VersionExecutor {
|
||||
command := VersionExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
binaryVersion: binaryVersion,
|
||||
buildTime: buildTime,
|
||||
|
@ -40,7 +33,7 @@ func newVersionCommand(name, summary string) *versionCommand {
|
|||
return &command
|
||||
}
|
||||
|
||||
func (c *versionCommand) Execute() error {
|
||||
func (c *VersionExecutor) Execute() error {
|
||||
var builder strings.Builder
|
||||
|
||||
if c.showFullVersion {
|
36
internal/executor/whoami.go
Normal file
36
internal/executor/whoami.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
||||
)
|
||||
|
||||
type WhoAmIExecutor struct {
|
||||
*flag.FlagSet
|
||||
|
||||
topLevelFlags TopLevelFlags
|
||||
}
|
||||
|
||||
func NewWhoAmIExecutor(tlf TopLevelFlags, name, summary string) *WhoAmIExecutor {
|
||||
whoExe := WhoAmIExecutor{
|
||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||
topLevelFlags: tlf,
|
||||
}
|
||||
|
||||
whoExe.Usage = commandUsageFunc(name, summary, whoExe.FlagSet)
|
||||
|
||||
return &whoExe
|
||||
}
|
||||
|
||||
func (c *WhoAmIExecutor) Execute() error {
|
||||
config, err := config.NewCredentialsConfigFromFile(c.topLevelFlags.ConfigDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to load the credential config; %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("You are logged in as %q.\n", config.CurrentAccount)
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue