From f6d67a98e097042a88168b40e40ae6b86cd910dd Mon Sep 17 00:00:00 2001 From: Dan Anglin Date: Tue, 21 May 2024 21:06:18 +0100 Subject: [PATCH] fix: use the account name instead of account ID The user will now specify the account name instead of the account ID when performing operations such as following and blocking. Enbas will lookup the account and retrieve the account ID before sending the request to GoToSocial. This prevents the user from having to retrieve the account ID themselves which should make it a bit easier to use. --- cmd/enbas/account.go | 76 +++++++++++++++++++++++++++++++ cmd/enbas/add.go | 26 +++++++---- cmd/enbas/block.go | 19 ++++---- cmd/enbas/errors.go | 6 +-- cmd/enbas/flags.go | 6 +-- cmd/enbas/follow.go | 19 ++++---- cmd/enbas/main.go | 23 +--------- cmd/enbas/remove.go | 26 +++++++---- cmd/enbas/show.go | 104 ++++++++++++++++--------------------------- 9 files changed, 177 insertions(+), 128 deletions(-) create mode 100644 cmd/enbas/account.go diff --git a/cmd/enbas/account.go b/cmd/enbas/account.go new file mode 100644 index 0000000..a7d6053 --- /dev/null +++ b/cmd/enbas/account.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + + "codeflow.dananglin.me.uk/apollo/enbas/internal/client" + "codeflow.dananglin.me.uk/apollo/enbas/internal/config" + "codeflow.dananglin.me.uk/apollo/enbas/internal/model" +) + +func getAccountID(gtsClient *client.Client, myAccount bool, accountName string) (string, error) { + var ( + accountID string + err error + ) + + switch { + case myAccount: + accountID, err = getMyAccountID(gtsClient) + if err != nil { + return "", fmt.Errorf("unable to get your account ID; %w", err) + } + case accountName != "": + accountID, err = getTheirAccountID(gtsClient, accountName) + if err != nil { + return "", fmt.Errorf("unable to get their account ID; %w", err) + } + default: + return "", noAccountSpecifiedError{} + } + + return accountID, nil +} + +func getTheirAccountID(gtsClient *client.Client, accountURI string) (string, error) { + account, err := getAccount(gtsClient, accountURI) + if err != nil { + return "", fmt.Errorf("unable to retrieve your account; %w", err) + } + + return account.ID, nil +} + +func getMyAccountID(gtsClient *client.Client) (string, error) { + account, err := getMyAccount(gtsClient) + if err != nil { + return "", fmt.Errorf("received an error while getting your account details; %w", err) + } + + return account.ID, nil +} + +func getMyAccount(gtsClient *client.Client) (model.Account, error) { + authConfig, err := config.NewAuthenticationConfigFromFile() + if err != nil { + return model.Account{}, fmt.Errorf("unable to retrieve the authentication configuration; %w", err) + } + + accountURI := authConfig.CurrentAccount + + account, err := getAccount(gtsClient, accountURI) + if err != nil { + return model.Account{}, fmt.Errorf("unable to retrieve your account; %w", err) + } + + return account, nil +} + +func getAccount(gtsClient *client.Client, accountURI string) (model.Account, error) { + account, err := gtsClient.GetAccount(accountURI) + if err != nil { + return model.Account{}, fmt.Errorf("unable to retrieve the account details; %w", err) + } + + return account, nil +} diff --git a/cmd/enbas/add.go b/cmd/enbas/add.go index a0612b7..b47c178 100644 --- a/cmd/enbas/add.go +++ b/cmd/enbas/add.go @@ -12,20 +12,20 @@ type addCommand struct { toResourceType string listID string - accountIDs accountIDs + accountNames accountNames } func newAddCommand(name, summary string) *addCommand { emptyArr := make([]string, 0, 3) command := addCommand{ - FlagSet: flag.NewFlagSet(name, flag.ExitOnError), - accountIDs: accountIDs(emptyArr), + FlagSet: flag.NewFlagSet(name, flag.ExitOnError), + accountNames: accountNames(emptyArr), } command.StringVar(&command.toResourceType, addToFlag, "", "specify the type of resource to add to") command.StringVar(&command.listID, listIDFlag, "", "the ID of the list to add to") - command.Var(&command.accountIDs, accountIDFlag, "the ID of the account to add to the list") + command.Var(&command.accountNames, accountNameFlag, "the name of the account to add to the resource") command.Usage = commandUsageFunc(name, summary, command.FlagSet) @@ -34,7 +34,7 @@ func newAddCommand(name, summary string) *addCommand { func (c *addCommand) Execute() error { if c.toResourceType == "" { - return flagNotSetError{flagText: "add-to"} + return flagNotSetError{flagText: addToFlag} } funcMap := map[string]func(*client.Client) error{ @@ -59,11 +59,21 @@ func (c *addCommand) addAccountsToList(gtsClient *client.Client) error { return flagNotSetError{flagText: listIDFlag} } - if len(c.accountIDs) == 0 { - return noAccountIDsSpecifiedError{} + if len(c.accountNames) == 0 { + return noAccountSpecifiedError{} } - if err := gtsClient.AddAccountsToList(c.listID, []string(c.accountIDs)); err != nil { + 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) } diff --git a/cmd/enbas/block.go b/cmd/enbas/block.go index 6eb6413..03a7069 100644 --- a/cmd/enbas/block.go +++ b/cmd/enbas/block.go @@ -11,7 +11,7 @@ type blockCommand struct { *flag.FlagSet resourceType string - accountID string + accountName string unblock bool } @@ -23,7 +23,7 @@ func newBlockCommand(name, summary string, unblock bool) *blockCommand { } command.StringVar(&command.resourceType, resourceTypeFlag, "", "specify the type of resource to block or unblock") - command.StringVar(&command.accountID, accountIDFlag, "", "specify the ID of the account you want to block or unblock") + command.StringVar(&command.accountName, accountNameFlag, "", "specify the account name in full (username@domain)") command.Usage = commandUsageFunc(name, summary, command.FlagSet) @@ -48,16 +48,17 @@ func (c *blockCommand) Execute() error { return doFunc(gtsClient) } -func (c *blockCommand) blockAccount(gts *client.Client) error { - if c.accountID == "" { - return flagNotSetError{flagText: accountIDFlag} +func (c *blockCommand) blockAccount(gtsClient *client.Client) error { + accountID, err := getAccountID(gtsClient, false, c.accountName) + if err != nil { + return fmt.Errorf("received an error while getting the account ID; %w", err) } if c.unblock { - return c.unblockAccount(gts) + return c.unblockAccount(gtsClient, accountID) } - if err := gts.BlockAccount(c.accountID); err != nil { + if err := gtsClient.BlockAccount(accountID); err != nil { return fmt.Errorf("unable to block the account; %w", err) } @@ -66,8 +67,8 @@ func (c *blockCommand) blockAccount(gts *client.Client) error { return nil } -func (c *blockCommand) unblockAccount(gts *client.Client) error { - if err := gts.UnblockAccount(c.accountID); err != 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) } diff --git a/cmd/enbas/errors.go b/cmd/enbas/errors.go index 8aa5dcc..e2be4f9 100644 --- a/cmd/enbas/errors.go +++ b/cmd/enbas/errors.go @@ -32,8 +32,8 @@ func (e unknownSubcommandError) Error() string { return "unknown subcommand '" + e.subcommand + "'" } -type noAccountIDsSpecifiedError struct{} +type noAccountSpecifiedError struct{} -func (e noAccountIDsSpecifiedError) Error() string { - return "no account IDs specified" +func (e noAccountSpecifiedError) Error() string { + return "no account specified in this request" } diff --git a/cmd/enbas/flags.go b/cmd/enbas/flags.go index 4856a45..df46ae5 100644 --- a/cmd/enbas/flags.go +++ b/cmd/enbas/flags.go @@ -2,13 +2,13 @@ package main import "strings" -type accountIDs []string +type accountNames []string -func (a *accountIDs) String() string { +func (a *accountNames) String() string { return strings.Join(*a, ", ") } -func (a *accountIDs) Set(value string) error { +func (a *accountNames) Set(value string) error { if len(value) > 0 { *a = append(*a, value) } diff --git a/cmd/enbas/follow.go b/cmd/enbas/follow.go index 20ff36d..ff0148e 100644 --- a/cmd/enbas/follow.go +++ b/cmd/enbas/follow.go @@ -11,7 +11,7 @@ type followCommand struct { *flag.FlagSet resourceType string - accountID string + accountName string showReposts bool notify bool unfollow bool @@ -25,7 +25,7 @@ func newFollowCommand(name, summary string, unfollow bool) *followCommand { } command.StringVar(&command.resourceType, resourceTypeFlag, "", "specify the type of resource to follow") - command.StringVar(&command.accountID, accountIDFlag, "", "specify the ID of the account you want to follow") + command.StringVar(&command.accountName, accountNameFlag, "", "specify the account name in full (username@domain)") command.BoolVar(&command.showReposts, showRepostsFlag, true, "show reposts from the account you want to follow") command.BoolVar(&command.notify, notifyFlag, false, "get notifications when the account you want to follow posts a status") @@ -52,16 +52,17 @@ func (c *followCommand) Execute() error { return doFunc(gtsClient) } -func (c *followCommand) followAccount(gts *client.Client) error { - if c.accountID == "" { - return flagNotSetError{flagText: accountIDFlag} +func (c *followCommand) followAccount(gtsClient *client.Client) error { + accountID, err := getAccountID(gtsClient, false, c.accountName) + if err != nil { + return fmt.Errorf("received an error while getting the account ID; %w", err) } if c.unfollow { - return c.unfollowAccount(gts) + return c.unfollowAccount(gtsClient, accountID) } - if err := gts.FollowAccount(c.accountID, c.showReposts, c.notify); err != nil { + if err := gtsClient.FollowAccount(accountID, c.showReposts, c.notify); err != nil { return fmt.Errorf("unable to follow the account; %w", err) } @@ -70,8 +71,8 @@ func (c *followCommand) followAccount(gts *client.Client) error { return nil } -func (c *followCommand) unfollowAccount(gts *client.Client) error { - if err := gts.UnfollowAccount(c.accountID); err != nil { +func (c *followCommand) unfollowAccount(gtsClient *client.Client, accountID string) error { + if err := gtsClient.UnfollowAccount(accountID); err != nil { return fmt.Errorf("unable to unfollow the account; %w", err) } diff --git a/cmd/enbas/main.go b/cmd/enbas/main.go index 792e024..485f290 100644 --- a/cmd/enbas/main.go +++ b/cmd/enbas/main.go @@ -4,15 +4,10 @@ import ( "flag" "fmt" "os" - - "codeflow.dananglin.me.uk/apollo/enbas/internal/client" - "codeflow.dananglin.me.uk/apollo/enbas/internal/config" - "codeflow.dananglin.me.uk/apollo/enbas/internal/model" ) const ( - accountFlag = "account" - accountIDFlag = "account-id" + accountNameFlag = "account-name" addToFlag = "add-to" instanceFlag = "instance" listIDFlag = "list-id" @@ -151,19 +146,3 @@ func run() error { return nil } - -func getMyAccount(gts *client.Client) (model.Account, error) { - authConfig, err := config.NewAuthenticationConfigFromFile() - if err != nil { - return model.Account{}, fmt.Errorf("unable to retrieve the authentication configuration; %w", err) - } - - accountURI := authConfig.CurrentAccount - - account, err := gts.GetAccount(accountURI) - if err != nil { - return model.Account{}, fmt.Errorf("unable to retrieve the account details; %w", err) - } - - return account, nil -} diff --git a/cmd/enbas/remove.go b/cmd/enbas/remove.go index 0c79676..9d388b1 100644 --- a/cmd/enbas/remove.go +++ b/cmd/enbas/remove.go @@ -12,20 +12,20 @@ type removeCommand struct { fromResourceType string listID string - accountIDs accountIDs + accountNames accountNames } func newRemoveCommand(name, summary string) *removeCommand { emptyArr := make([]string, 0, 3) command := removeCommand{ - FlagSet: flag.NewFlagSet(name, flag.ExitOnError), - accountIDs: accountIDs(emptyArr), + FlagSet: flag.NewFlagSet(name, flag.ExitOnError), + accountNames: accountNames(emptyArr), } command.StringVar(&command.fromResourceType, removeFromFlag, "", "specify the type of resource to remove from") command.StringVar(&command.listID, listIDFlag, "", "the ID of the list to remove from") - command.Var(&command.accountIDs, accountIDFlag, "the ID of the account to remove from the list") + command.Var(&command.accountNames, accountNameFlag, "the name of the account to remove from the resource") command.Usage = commandUsageFunc(name, summary, command.FlagSet) @@ -34,7 +34,7 @@ func newRemoveCommand(name, summary string) *removeCommand { func (c *removeCommand) Execute() error { if c.fromResourceType == "" { - return flagNotSetError{flagText: "remove-from"} + return flagNotSetError{flagText: removeFromFlag} } funcMap := map[string]func(*client.Client) error{ @@ -59,11 +59,21 @@ func (c *removeCommand) removeAccountsFromList(gtsClient *client.Client) error { return flagNotSetError{flagText: listIDFlag} } - if len(c.accountIDs) == 0 { - return noAccountIDsSpecifiedError{} + if len(c.accountNames) == 0 { + return noAccountSpecifiedError{} } - if err := gtsClient.RemoveAccountsFromList(c.listID, []string(c.accountIDs)); err != nil { + 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) } diff --git a/cmd/enbas/show.go b/cmd/enbas/show.go index ad0939d..79014e4 100644 --- a/cmd/enbas/show.go +++ b/cmd/enbas/show.go @@ -15,8 +15,7 @@ type showCommand struct { showAccountRelationship bool showUserPreferences bool resourceType string - account string - accountID string + accountName string statusID string timelineCategory string listID string @@ -33,8 +32,7 @@ func newShowCommand(name, summary string) *showCommand { command.BoolVar(&command.showAccountRelationship, showAccountRelationshipFlag, false, "show your relationship to the specified account") command.BoolVar(&command.showUserPreferences, showUserPreferencesFlag, false, "show your preferences") command.StringVar(&command.resourceType, resourceTypeFlag, "", "specify the type of resource to display") - command.StringVar(&command.account, accountFlag, "", "specify the account URI to lookup") - command.StringVar(&command.accountID, accountIDFlag, "", "specify the account ID") + command.StringVar(&command.accountName, accountNameFlag, "", "specify the account name in full (username@domain)") command.StringVar(&command.statusID, statusIDFlag, "", "specify the ID of the status to display") command.StringVar(&command.timelineCategory, timelineCategoryFlag, "home", "specify the type of timeline to display (valid values are home, public, list and tag)") command.StringVar(&command.listID, listIDFlag, "", "specify the ID of the list to display") @@ -75,8 +73,8 @@ func (c *showCommand) Execute() error { return doFunc(gtsClient) } -func (c *showCommand) showInstance(gts *client.Client) error { - instance, err := gts.GetInstance() +func (c *showCommand) showInstance(gtsClient *client.Client) error { + instance, err := gtsClient.GetInstance() if err != nil { return fmt.Errorf("unable to retrieve the instance details; %w", err) } @@ -86,34 +84,32 @@ func (c *showCommand) showInstance(gts *client.Client) error { return nil } -func (c *showCommand) showAccount(gts *client.Client) error { +func (c *showCommand) showAccount(gtsClient *client.Client) error { var ( account model.Account err error ) if c.myAccount { - account, err = getMyAccount(gts) + account, err = getMyAccount(gtsClient) if err != nil { - return fmt.Errorf("received an error while getting account details; %w", err) + return fmt.Errorf("received an error while getting the account details; %w", err) } } else { - if c.account == "" { - return flagNotSetError{flagText: accountFlag} + if c.accountName == "" { + return flagNotSetError{flagText: accountNameFlag} } - accountURI := c.account - - account, err = gts.GetAccount(accountURI) + account, err = getAccount(gtsClient, c.accountName) if err != nil { - return fmt.Errorf("unable to retrieve the account details; %w", err) + return fmt.Errorf("received an error while getting the account details; %w", err) } } fmt.Println(account) if !c.myAccount && c.showAccountRelationship { - relationship, err := gts.GetAccountRelationship(account.ID) + relationship, err := gtsClient.GetAccountRelationship(account.ID) if err != nil { return fmt.Errorf("unable to retrieve the relationship to this account; %w", err) } @@ -122,7 +118,7 @@ func (c *showCommand) showAccount(gts *client.Client) error { } if c.myAccount && c.showUserPreferences { - preferences, err := gts.GetUserPreferences() + preferences, err := gtsClient.GetUserPreferences() if err != nil { return fmt.Errorf("unable to retrieve the user preferences; %w", err) } @@ -133,12 +129,12 @@ func (c *showCommand) showAccount(gts *client.Client) error { return nil } -func (c *showCommand) showStatus(gts *client.Client) error { +func (c *showCommand) showStatus(gtsClient *client.Client) error { if c.statusID == "" { return flagNotSetError{flagText: statusIDFlag} } - status, err := gts.GetStatus(c.statusID) + status, err := gtsClient.GetStatus(c.statusID) if err != nil { return fmt.Errorf("unable to retrieve the status; %w", err) } @@ -148,7 +144,7 @@ func (c *showCommand) showStatus(gts *client.Client) error { return nil } -func (c *showCommand) showTimeline(gts *client.Client) error { +func (c *showCommand) showTimeline(gtsClient *client.Client) error { var ( timeline model.Timeline err error @@ -156,21 +152,21 @@ func (c *showCommand) showTimeline(gts *client.Client) error { switch c.timelineCategory { case "home": - timeline, err = gts.GetHomeTimeline(c.limit) + timeline, err = gtsClient.GetHomeTimeline(c.limit) case "public": - timeline, err = gts.GetPublicTimeline(c.limit) + timeline, err = gtsClient.GetPublicTimeline(c.limit) case "list": if c.listID == "" { return flagNotSetError{flagText: listIDFlag} } - timeline, err = gts.GetListTimeline(c.listID, c.limit) + timeline, err = gtsClient.GetListTimeline(c.listID, c.limit) case "tag": if c.tag == "" { return flagNotSetError{flagText: tagFlag} } - timeline, err = gts.GetTagTimeline(c.tag, c.limit) + timeline, err = gtsClient.GetTagTimeline(c.tag, c.limit) default: return invalidTimelineCategoryError{category: c.timelineCategory} } @@ -190,17 +186,17 @@ func (c *showCommand) showTimeline(gts *client.Client) error { return nil } -func (c *showCommand) showList(gts *client.Client) error { +func (c *showCommand) showList(gtsClient *client.Client) error { if c.listID == "" { - return c.showLists(gts) + return c.showLists(gtsClient) } - list, err := gts.GetList(c.listID) + list, err := gtsClient.GetList(c.listID) if err != nil { return fmt.Errorf("unable to retrieve the list; %w", err) } - accounts, err := gts.GetAccountsFromList(c.listID, 0) + accounts, err := gtsClient.GetAccountsFromList(c.listID, 0) if err != nil { return fmt.Errorf("unable to retrieve the accounts from the list; %w", err) } @@ -219,8 +215,8 @@ func (c *showCommand) showList(gts *client.Client) error { return nil } -func (c *showCommand) showLists(gts *client.Client) error { - lists, err := gts.GetAllLists() +func (c *showCommand) showLists(gtsClient *client.Client) error { + lists, err := gtsClient.GetAllLists() if err != nil { return fmt.Errorf("unable to retrieve the lists; %w", err) } @@ -237,25 +233,13 @@ func (c *showCommand) showLists(gts *client.Client) error { return nil } -func (c *showCommand) showFollowers(gts *client.Client) error { - var accountID string - - if c.myAccount { - account, err := getMyAccount(gts) - if err != nil { - return fmt.Errorf("received an error while getting account details; %w", err) - } - - accountID = account.ID - } else { - if c.accountID == "" { - return flagNotSetError{flagText: accountIDFlag} - } - - accountID = c.accountID +func (c *showCommand) showFollowers(gtsClient *client.Client) error { + accountID, err := getAccountID(gtsClient, c.myAccount, c.accountName) + if err != nil { + return fmt.Errorf("received an error while getting the account ID; %w", err) } - followers, err := gts.GetFollowers(accountID, c.limit) + followers, err := gtsClient.GetFollowers(accountID, c.limit) if err != nil { return fmt.Errorf("unable to retrieve the list of followers; %w", err) } @@ -269,25 +253,13 @@ func (c *showCommand) showFollowers(gts *client.Client) error { return nil } -func (c *showCommand) showFollowing(gts *client.Client) error { - var accountID string - - if c.myAccount { - account, err := getMyAccount(gts) - if err != nil { - return fmt.Errorf("received an error while getting account details; %w", err) - } - - accountID = account.ID - } else { - if c.accountID == "" { - return flagNotSetError{flagText: accountIDFlag} - } - - accountID = c.accountID +func (c *showCommand) showFollowing(gtsClient *client.Client) error { + accountID, err := getAccountID(gtsClient, c.myAccount, c.accountName) + if err != nil { + return fmt.Errorf("received an error while getting the account ID; %w", err) } - following, err := gts.GetFollowing(accountID, c.limit) + following, err := gtsClient.GetFollowing(accountID, c.limit) if err != nil { return fmt.Errorf("unable to retrieve the list of followed accounts; %w", err) } @@ -301,8 +273,8 @@ func (c *showCommand) showFollowing(gts *client.Client) error { return nil } -func (c *showCommand) showBlocked(gts *client.Client) error { - blocked, err := gts.GetBlockedAccounts(c.limit) +func (c *showCommand) 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) }