diff --git a/internal/client/accounts.go b/internal/client/accounts.go index 85a3d39..1f9161c 100644 --- a/internal/client/accounts.go +++ b/internal/client/accounts.go @@ -39,21 +39,27 @@ func (g *Client) GetAccount(accountURI string) (model.Account, error) { return account, nil } -func (g *Client) GetAccountRelationship(accountID string) (model.AccountRelationship, error) { +func (g *Client) GetAccountRelationship(accountID string) (*model.AccountRelationship, error) { path := "/api/v1/accounts/relationships?id=" + accountID url := g.Authentication.Instance + path var relationships []model.AccountRelationship if err := g.sendRequest(http.MethodGet, url, nil, &relationships); err != nil { - return model.AccountRelationship{}, fmt.Errorf("received an error after sending the request to get the account relationship: %w", err) + return nil, fmt.Errorf( + "received an error after sending the request to get the account relationship: %w", + err, + ) } if len(relationships) != 1 { - return model.AccountRelationship{}, fmt.Errorf("unexpected number of account relationships returned: want 1, got %d", len(relationships)) + return nil, fmt.Errorf( + "unexpected number of account relationships returned: want 1, got %d", + len(relationships), + ) } - return relationships[0], nil + return &relationships[0], nil } type FollowAccountForm struct { diff --git a/internal/client/preferences.go b/internal/client/preferences.go index a424344..cc8a88f 100644 --- a/internal/client/preferences.go +++ b/internal/client/preferences.go @@ -11,14 +11,14 @@ import ( "codeflow.dananglin.me.uk/apollo/enbas/internal/model" ) -func (g *Client) GetUserPreferences() (model.Preferences, error) { +func (g *Client) GetUserPreferences() (*model.Preferences, error) { url := g.Authentication.Instance + "/api/v1/preferences" var preferences model.Preferences if err := g.sendRequest(http.MethodGet, url, nil, &preferences); err != nil { - return model.Preferences{}, fmt.Errorf("received an error after sending the request to get the user preferences: %w", err) + return nil, fmt.Errorf("received an error after sending the request to get the user preferences: %w", err) } - return preferences, nil + return &preferences, nil } diff --git a/internal/executor/show.go b/internal/executor/show.go index 17ae3b7..03a48e8 100644 --- a/internal/executor/show.go +++ b/internal/executor/show.go @@ -132,26 +132,27 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error { return nil } - s.printer.PrintAccount(account) + var ( + relationship *model.AccountRelationship = nil + preferences *model.Preferences = nil + ) if !s.myAccount && !s.skipAccountRelationship { - relationship, err := gtsClient.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) } - - s.printer.PrintAccountRelationship(relationship) } if s.myAccount && s.showUserPreferences { - preferences, err := gtsClient.GetUserPreferences() + preferences, err = gtsClient.GetUserPreferences() if err != nil { return fmt.Errorf("unable to retrieve the user preferences: %w", err) } - - utilities.Display(preferences, false, "") } + s.printer.PrintAccount(account, relationship, preferences) + return nil } diff --git a/internal/model/preferences.go b/internal/model/preferences.go index 94bd77e..c20023e 100644 --- a/internal/model/preferences.go +++ b/internal/model/preferences.go @@ -4,12 +4,6 @@ package model -import ( - "fmt" - - "codeflow.dananglin.me.uk/apollo/enbas/internal/utilities" -) - type Preferences struct { PostingDefaultVisibility string `json:"posting:default:visibility"` PostingDefaultSensitive bool `json:"posting:default:sensitive"` @@ -18,19 +12,3 @@ type Preferences struct { ReadingExpandSpoilers bool `json:"reading:expand:spoilers"` ReadingAutoplayGifs bool `json:"reading:autoplay:gifs"` } - -func (p Preferences) Display(noColor bool) string { - format := ` -%s - %s: %s - %s: %s - %s: %t` - - return fmt.Sprintf( - format, - utilities.HeaderFormat(noColor, "YOUR PREFERENCES:"), - utilities.FieldFormat(noColor, "Default post language"), p.PostingDefaultLanguage, - utilities.FieldFormat(noColor, "Default post visibility"), p.PostingDefaultVisibility, - utilities.FieldFormat(noColor, "Mark posts as sensitive by default"), p.PostingDefaultSensitive, - ) -} diff --git a/internal/printer/account.go b/internal/printer/account.go index e6c5b5e..88b3b2d 100644 --- a/internal/printer/account.go +++ b/internal/printer/account.go @@ -8,7 +8,7 @@ import ( "codeflow.dananglin.me.uk/apollo/enbas/internal/utilities" ) -func (p Printer) PrintAccount(account model.Account) { +func (p Printer) PrintAccount(account model.Account, relationship *model.AccountRelationship, preferences *model.Preferences) { var builder strings.Builder builder.WriteString("\n" + p.fullDisplayNameFormat(account.DisplayName, account.Acct)) @@ -32,11 +32,73 @@ func (p Printer) PrintAccount(account model.Account) { } builder.WriteString("\n\n" + p.headerFormat("ACCOUNT URL:")) - builder.WriteString("\n" + account.URL + "\n") + builder.WriteString("\n" + account.URL) + + if relationship != nil { + builder.WriteString(p.accountRelationship(relationship)) + } + + if preferences != nil { + builder.WriteString(p.userPreferences(preferences)) + } + + builder.WriteString("\n\n") printToStdout(builder.String()) } +func (p Printer) accountRelationship(relationship *model.AccountRelationship) string { + var builder strings.Builder + + builder.WriteString("\n\n" + p.headerFormat("YOUR RELATIONSHIP WITH THIS ACCOUNT:")) + builder.WriteString("\n" + p.fieldFormat("Following:")) + builder.WriteString(" " + strconv.FormatBool(relationship.Following)) + builder.WriteString("\n" + p.fieldFormat("Is following you:")) + builder.WriteString(" " + strconv.FormatBool(relationship.FollowedBy)) + builder.WriteString("\n" + p.fieldFormat("A follow request was sent and is pending:")) + builder.WriteString(" " + strconv.FormatBool(relationship.FollowRequested)) + builder.WriteString("\n" + p.fieldFormat("Received a pending follow request:")) + builder.WriteString(" " + strconv.FormatBool(relationship.FollowRequestedBy)) + builder.WriteString("\n" + p.fieldFormat("Endorsed:")) + builder.WriteString(" " + strconv.FormatBool(relationship.Endorsed)) + builder.WriteString("\n" + p.fieldFormat("Showing Reposts (boosts):")) + builder.WriteString(" " + strconv.FormatBool(relationship.ShowingReblogs)) + builder.WriteString("\n" + p.fieldFormat("Muted:")) + builder.WriteString(" " + strconv.FormatBool(relationship.Muting)) + builder.WriteString("\n" + p.fieldFormat("Notifications muted:")) + builder.WriteString(" " + strconv.FormatBool(relationship.MutingNotifications)) + builder.WriteString("\n" + p.fieldFormat("Blocking:")) + builder.WriteString(" " + strconv.FormatBool(relationship.Blocking)) + builder.WriteString("\n" + p.fieldFormat("Is blocking you:")) + builder.WriteString(" " + strconv.FormatBool(relationship.BlockedBy)) + builder.WriteString("\n" + p.fieldFormat("Blocking account's domain:")) + builder.WriteString(" " + strconv.FormatBool(relationship.DomainBlocking)) + + if relationship.PrivateNote != "" { + builder.WriteString("\n\n" + p.headerFormat("YOUR PRIVATE NOTE ABOUT THIS ACCOUNT:")) + builder.WriteString("\n" + utilities.WrapLines(relationship.PrivateNote, "\n", p.maxTerminalWidth)) + } + + return builder.String() +} + +func (p Printer) userPreferences(preferences *model.Preferences) string { + var builder strings.Builder + + builder.WriteString("\n\n" + p.headerFormat("YOUR PREFERENCES:")) + + builder.WriteString("\n" + p.fieldFormat("Default post language:")) + builder.WriteString(" " + preferences.PostingDefaultLanguage) + + builder.WriteString("\n" + p.fieldFormat("Default post visibility:")) + builder.WriteString(" " + preferences.PostingDefaultVisibility) + + builder.WriteString("\n" + p.fieldFormat("Mark posts as sensitive by default:")) + builder.WriteString(" " + strconv.FormatBool(preferences.PostingDefaultSensitive)) + + return builder.String() +} + func (p Printer) PrintAccountList(list model.AccountList) { var builder strings.Builder @@ -69,40 +131,3 @@ func (p Printer) PrintAccountList(list model.AccountList) { printToStdout(builder.String()) } - -func (p Printer) PrintAccountRelationship(relationship model.AccountRelationship) { - var builder strings.Builder - - builder.WriteString("\n" + p.headerFormat("YOUR RELATIONSHIP WITH THIS ACCOUNT:")) - builder.WriteString("\n" + p.fieldFormat("Following:")) - builder.WriteString(" " + strconv.FormatBool(relationship.Following)) - builder.WriteString("\n" + p.fieldFormat("Is following you:")) - builder.WriteString(" " + strconv.FormatBool(relationship.FollowedBy)) - builder.WriteString("\n" + p.fieldFormat("A follow request was sent and is pending:")) - builder.WriteString(" " + strconv.FormatBool(relationship.FollowRequested)) - builder.WriteString("\n" + p.fieldFormat("Received a pending follow request:")) - builder.WriteString(" " + strconv.FormatBool(relationship.FollowRequestedBy)) - builder.WriteString("\n" + p.fieldFormat("Endorsed:")) - builder.WriteString(" " + strconv.FormatBool(relationship.Endorsed)) - builder.WriteString("\n" + p.fieldFormat("Showing Reposts (boosts):")) - builder.WriteString(" " + strconv.FormatBool(relationship.ShowingReblogs)) - builder.WriteString("\n" + p.fieldFormat("Muted:")) - builder.WriteString(" " + strconv.FormatBool(relationship.Muting)) - builder.WriteString("\n" + p.fieldFormat("Notifications muted:")) - builder.WriteString(" " + strconv.FormatBool(relationship.MutingNotifications)) - builder.WriteString("\n" + p.fieldFormat("Blocking:")) - builder.WriteString(" " + strconv.FormatBool(relationship.Blocking)) - builder.WriteString("\n" + p.fieldFormat("Is blocking you:")) - builder.WriteString(" " + strconv.FormatBool(relationship.BlockedBy)) - builder.WriteString("\n" + p.fieldFormat("Blocking account's domain:")) - builder.WriteString(" " + strconv.FormatBool(relationship.DomainBlocking)) - - if relationship.PrivateNote != "" { - builder.WriteString("\n\n" + p.headerFormat("YOUR PRIVATE NOTE ABOUT THIS ACCOUNT:")) - builder.WriteString("\n" + utilities.WrapLines(relationship.PrivateNote, "\n", p.maxTerminalWidth)) - } - - builder.WriteString("\n\n") - - printToStdout(builder.String()) -} diff --git a/internal/printer/poll.go b/internal/printer/poll.go index b1c82d7..a109411 100644 --- a/internal/printer/poll.go +++ b/internal/printer/poll.go @@ -6,7 +6,6 @@ import ( "strings" "codeflow.dananglin.me.uk/apollo/enbas/internal/model" - "codeflow.dananglin.me.uk/apollo/enbas/internal/utilities" ) func (p Printer) PrintPoll(poll model.Poll) { @@ -62,7 +61,7 @@ func (p Printer) pollOptions(poll model.Poll) string { builder.WriteString("\n\n" + p.fieldFormat("Total votes:") + " " + strconv.Itoa(poll.VotesCount)) builder.WriteString("\n" + p.fieldFormat("Poll ID:") + " " + poll.ID) - builder.WriteString("\n" + p.fieldFormat("Poll is open until:") + " " + utilities.FormatTime(poll.ExpiredAt)) + builder.WriteString("\n" + p.fieldFormat("Poll is open until:") + " " + p.formatDateTime(poll.ExpiredAt)) return builder.String() } diff --git a/internal/printer/status.go b/internal/printer/status.go index e766f41..94890b2 100644 --- a/internal/printer/status.go +++ b/internal/printer/status.go @@ -82,7 +82,7 @@ func (p Printer) PrintStatusList(list model.StatusList) { builder.WriteString( "\n\n" + p.fieldFormat("Status ID:") + " " + statusID + "\t" + - p.fieldFormat("Created at:") + " " + utilities.FormatTime(createdAt) + + p.fieldFormat("Created at:") + " " + p.formatDateTime(createdAt) + "\n", ) diff --git a/internal/utilities/displayer.go b/internal/utilities/displayer.go deleted file mode 100644 index a595c2a..0000000 --- a/internal/utilities/displayer.go +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Dan Anglin -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package utilities - -import ( - "fmt" - "os" - "os/exec" - "strings" -) - -type Displayer interface { - Display(noColor bool) string -} - -func Display(displayer Displayer, noColor bool, pagerCommand string) { - if pagerCommand == "" { - os.Stdout.WriteString(displayer.Display(noColor) + "\n") - - return - } - - split := strings.Split(pagerCommand, " ") - - pager := new(exec.Cmd) - - if len(split) == 1 { - pager = exec.Command(split[0]) //nolint:gosec - } else { - pager = exec.Command(split[0], split[1:]...) //nolint:gosec - } - - pipe, err := pager.StdinPipe() - if err != nil { - os.Stdout.WriteString(displayer.Display(noColor) + "\n") - - return - } - - pager.Stdout = os.Stdout - pager.Stderr = os.Stderr - - _ = pager.Start() - - defer func() { - _ = pipe.Close() - _ = pager.Wait() - }() - - fmt.Fprintln(pipe, displayer.Display(noColor)+"\n") -} diff --git a/internal/utilities/format.go b/internal/utilities/format.go deleted file mode 100644 index 9509e7b..0000000 --- a/internal/utilities/format.go +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Dan Anglin -// -// SPDX-License-Identifier: GPL-3.0-or-later - -package utilities - -import ( - "regexp" - "strings" - "time" -) - -const ( - reset = "\033[0m" - boldblue = "\033[34;1m" - boldmagenta = "\033[35;1m" - green = "\033[32m" -) - -func HeaderFormat(noColor bool, text string) string { - if noColor { - return text - } - - return boldblue + text + reset -} - -func FieldFormat(noColor bool, text string) string { - if noColor { - return text - } - - return green + text + reset -} - -func FullDisplayNameFormat(noColor bool, displayName, acct string) string { - // use this pattern to remove all emoji strings - pattern := regexp.MustCompile(`\s:[A-Za-z0-9_]*:`) - - var builder strings.Builder - - if noColor { - builder.WriteString(pattern.ReplaceAllString(displayName, "")) - } else { - builder.WriteString(boldmagenta + pattern.ReplaceAllString(displayName, "") + reset) - } - - builder.WriteString(" (@" + acct + ")") - - return builder.String() -} - -func FormatDate(date time.Time) string { - return date.Local().Format("02 Jan 2006") -} - -func FormatTime(date time.Time) string { - return date.Local().Format("02 Jan 2006, 15:04 (MST)") -}