Compare commits

..

4 commits

10 changed files with 335 additions and 233 deletions

View file

@ -109,7 +109,16 @@ func (a *AddExecutor) addAccountsToList(gtsClient *client.Client) error {
for ind := range a.accountNames { for ind := range a.accountNames {
accountID, err := getTheirAccountID(gtsClient, a.accountNames[ind]) accountID, err := getTheirAccountID(gtsClient, a.accountNames[ind])
if err != nil { if err != nil {
return fmt.Errorf("unable to get the account ID for %s, %w", a.accountNames[ind], err) return fmt.Errorf("unable to get the account ID for %s: %w", a.accountNames[ind], err)
}
relationship, err := gtsClient.GetAccountRelationship(accountID)
if err != nil {
return fmt.Errorf("unable to get your relationship to %s: %w", a.accountNames[ind], err)
}
if !relationship.Following {
return NotFollowingError{Account: a.accountNames[ind]}
} }
accountIDs[ind] = accountID accountIDs[ind] = accountID

View file

@ -94,3 +94,11 @@ func (e NoPollOptionError) Error() string {
flagPollOption + flagPollOption +
" flag to add options to the poll" " flag to add options to the poll"
} }
type NotFollowingError struct {
Account string
}
func (e NotFollowingError) Error() string {
return "you are not following " + e.Account
}

View file

@ -132,7 +132,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
return nil return nil
} }
utilities.Display(account, false, "") s.printer.PrintAccount(account)
if !s.myAccount && !s.skipAccountRelationship { if !s.myAccount && !s.skipAccountRelationship {
relationship, err := gtsClient.GetAccountRelationship(account.ID) relationship, err := gtsClient.GetAccountRelationship(account.ID)
@ -140,7 +140,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
return fmt.Errorf("unable to retrieve the relationship to this account: %w", err) return fmt.Errorf("unable to retrieve the relationship to this account: %w", err)
} }
utilities.Display(relationship, false, "") s.printer.PrintAccountRelationship(relationship)
} }
if s.myAccount && s.showUserPreferences { if s.myAccount && s.showUserPreferences {
@ -171,7 +171,7 @@ func (s *ShowExecutor) showStatus(gtsClient *client.Client) error {
return nil return nil
} }
utilities.Display(status, false, "") s.printer.PrintStatus(status)
return nil return nil
} }
@ -220,7 +220,7 @@ func (s *ShowExecutor) showTimeline(gtsClient *client.Client) error {
return nil return nil
} }
utilities.Display(timeline, false, "") s.printer.PrintStatusList(timeline)
return nil return nil
} }
@ -283,7 +283,7 @@ func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error {
} }
if len(followers.Accounts) > 0 { if len(followers.Accounts) > 0 {
utilities.Display(followers, false, "") s.printer.PrintAccountList(followers)
} else { } else {
s.printer.PrintInfo("There are no followers for this account (or the list is hidden).\n") s.printer.PrintInfo("There are no followers for this account (or the list is hidden).\n")
} }
@ -303,7 +303,7 @@ func (s *ShowExecutor) showFollowing(gtsClient *client.Client) error {
} }
if len(following.Accounts) > 0 { if len(following.Accounts) > 0 {
utilities.Display(following, false, "") s.printer.PrintAccountList(following)
} else { } else {
s.printer.PrintInfo("This account is not following anyone or the list is hidden.\n") s.printer.PrintInfo("This account is not following anyone or the list is hidden.\n")
} }
@ -318,7 +318,7 @@ func (s *ShowExecutor) showBlocked(gtsClient *client.Client) error {
} }
if len(blocked.Accounts) > 0 { if len(blocked.Accounts) > 0 {
utilities.Display(blocked, false, "") s.printer.PrintAccountList(blocked)
} else { } else {
s.printer.PrintInfo("You have no blocked accounts.\n") s.printer.PrintInfo("You have no blocked accounts.\n")
} }
@ -333,7 +333,7 @@ func (s *ShowExecutor) showBookmarks(gtsClient *client.Client) error {
} }
if len(bookmarks.Statuses) > 0 { if len(bookmarks.Statuses) > 0 {
utilities.Display(bookmarks, false, "") s.printer.PrintStatusList(bookmarks)
} else { } else {
s.printer.PrintInfo("You have no bookmarks.\n") s.printer.PrintInfo("You have no bookmarks.\n")
} }
@ -348,7 +348,7 @@ func (s *ShowExecutor) showLiked(gtsClient *client.Client) error {
} }
if len(liked.Statuses) > 0 { if len(liked.Statuses) > 0 {
utilities.Display(liked, false, "") s.printer.PrintStatusList(liked)
} else { } else {
s.printer.PrintInfo("You have no " + s.resourceType + " statuses.\n") s.printer.PrintInfo("You have no " + s.resourceType + " statuses.\n")
} }
@ -363,7 +363,7 @@ func (s *ShowExecutor) showFollowRequests(gtsClient *client.Client) error {
} }
if len(accounts.Accounts) > 0 { if len(accounts.Accounts) > 0 {
utilities.Display(accounts, false, "") s.printer.PrintAccountList(accounts)
} else { } else {
s.printer.PrintInfo("You have no follow requests.\n") s.printer.PrintInfo("You have no follow requests.\n")
} }

View file

@ -5,10 +5,7 @@
package model package model
import ( import (
"fmt"
"time" "time"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
) )
type Account struct { type Account struct {
@ -63,59 +60,6 @@ type Field struct {
VerifiedAt string `json:"verified_at"` VerifiedAt string `json:"verified_at"`
} }
func (a Account) Display(noColor bool) string {
format := `
%s
%s
%s
%s
%s
%s
%s %d
%s %d
%s %d
%s
%s
%s %s
%s
%s`
metadata := ""
for _, field := range a.Fields {
metadata += fmt.Sprintf(
"\n %s: %s",
utilities.FieldFormat(noColor, field.Name),
utilities.ConvertHTMLToText(field.Value),
)
}
return fmt.Sprintf(
format,
utilities.FullDisplayNameFormat(noColor, a.DisplayName, a.Acct),
utilities.HeaderFormat(noColor, "ACCOUNT ID:"),
a.ID,
utilities.HeaderFormat(noColor, "JOINED ON:"),
utilities.FormatDate(a.CreatedAt),
utilities.HeaderFormat(noColor, "STATS:"),
utilities.FieldFormat(noColor, "Followers:"), a.FollowersCount,
utilities.FieldFormat(noColor, "Following:"), a.FollowingCount,
utilities.FieldFormat(noColor, "Statuses:"), a.StatusCount,
utilities.HeaderFormat(noColor, "BIOGRAPHY:"),
utilities.WrapLines(utilities.ConvertHTMLToText(a.Note), "\n ", 80),
utilities.HeaderFormat(noColor, "METADATA:"),
metadata,
utilities.HeaderFormat(noColor, "ACCOUNT URL:"),
a.URL,
)
}
type AccountRelationship struct { type AccountRelationship struct {
ID string `json:"id"` ID string `json:"id"`
PrivateNote string `json:"note"` PrivateNote string `json:"note"`
@ -133,53 +77,6 @@ type AccountRelationship struct {
ShowingReblogs bool `json:"showing_reblogs"` ShowingReblogs bool `json:"showing_reblogs"`
} }
func (a AccountRelationship) Display(noColor bool) string {
format := `
%s
%s: %t
%s: %t
%s: %t
%s: %t
%s: %t
%s: %t
%s: %t
%s: %t
%s: %t
%s: %t
%s: %t`
privateNoteFormat := `
%s
%s`
output := fmt.Sprintf(
format,
utilities.HeaderFormat(noColor, "YOUR RELATIONSHIP WITH THIS ACCOUNT:"),
utilities.FieldFormat(noColor, "Following"), a.Following,
utilities.FieldFormat(noColor, "Is following you"), a.FollowedBy,
utilities.FieldFormat(noColor, "A follow request was sent and is pending"), a.FollowRequested,
utilities.FieldFormat(noColor, "Received a pending follow request"), a.FollowRequestedBy,
utilities.FieldFormat(noColor, "Endorsed"), a.Endorsed,
utilities.FieldFormat(noColor, "Showing Reposts (boosts)"), a.ShowingReblogs,
utilities.FieldFormat(noColor, "Muted"), a.Muting,
utilities.FieldFormat(noColor, "Notifications muted"), a.MutingNotifications,
utilities.FieldFormat(noColor, "Blocking"), a.Blocking,
utilities.FieldFormat(noColor, "Is blocking you"), a.BlockedBy,
utilities.FieldFormat(noColor, "Blocking account's domain"), a.DomainBlocking,
)
if a.PrivateNote != "" {
output += "\n"
output += fmt.Sprintf(
privateNoteFormat,
utilities.HeaderFormat(noColor, "YOUR PRIVATE NOTE ABOUT THIS ACCOUNT:"),
utilities.WrapLines(a.PrivateNote, "\n ", 80),
)
}
return output
}
type AccountListType int type AccountListType int
const ( const (
@ -193,36 +90,3 @@ type AccountList struct {
Type AccountListType Type AccountListType
Accounts []Account Accounts []Account
} }
func (a AccountList) Display(noColor bool) string {
output := "\n"
switch a.Type {
case AccountListFollowers:
output += utilities.HeaderFormat(noColor, "Followed by:")
case AccountListFollowing:
output += utilities.HeaderFormat(noColor, "Following:")
case AccountListBlockedAccount:
output += utilities.HeaderFormat(noColor, "Blocked accounts:")
case AccountListFollowRequests:
output += utilities.HeaderFormat(noColor, "Accounts that have requested to follow you:")
default:
output += utilities.HeaderFormat(noColor, "Accounts:")
}
if a.Type == AccountListBlockedAccount {
for i := range a.Accounts {
output += fmt.Sprintf(
"\n • %s (%s)",
a.Accounts[i].Acct,
a.Accounts[i].ID,
)
}
} else {
for i := range a.Accounts {
output += "\n • " + utilities.FullDisplayNameFormat(noColor, a.Accounts[i].DisplayName, a.Accounts[i].Acct)
}
}
return output
}

View file

@ -5,11 +5,7 @@
package model package model
import ( import (
"strconv"
"strings"
"time" "time"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
) )
type Status struct { type Status struct {
@ -139,86 +135,7 @@ type MediaDimensions struct {
Width int `json:"width"` Width int `json:"width"`
} }
func (s Status) Display(noColor bool) string {
indent := " "
var builder strings.Builder
// The account information
builder.WriteString(utilities.FullDisplayNameFormat(noColor, s.Account.DisplayName, s.Account.Acct) + "\n\n")
// The content of the status.
builder.WriteString(utilities.HeaderFormat(noColor, "CONTENT:"))
builder.WriteString(utilities.WrapLines(utilities.ConvertHTMLToText(s.Content), "\n ", 80))
// If a poll exists in a status, write the contents to the builder.
if s.Poll != nil {
displayPollContent(&builder, *s.Poll, noColor, indent)
}
// The ID of the status
builder.WriteString("\n\n" + utilities.HeaderFormat(noColor, "STATUS ID:") + "\n" + indent + s.ID)
// Status creation time
builder.WriteString("\n\n" + utilities.HeaderFormat(noColor, "CREATED AT:") + "\n" + indent + utilities.FormatTime(s.CreatedAt))
// Status stats
builder.WriteString(
"\n\n" +
utilities.HeaderFormat(noColor, "STATS:") +
"\n" + indent + utilities.FieldFormat(noColor, "Boosts: ") + strconv.Itoa(s.ReblogsCount) +
"\n" + indent + utilities.FieldFormat(noColor, "Likes: ") + strconv.Itoa(s.FavouritesCount) +
"\n" + indent + utilities.FieldFormat(noColor, "Replies: ") + strconv.Itoa(s.RepliesCount),
)
// Status visibility
builder.WriteString("\n\n" + utilities.HeaderFormat(noColor, "VISIBILITY:") + "\n" + indent + s.Visibility.String())
// Status URL
builder.WriteString("\n\n" + utilities.HeaderFormat(noColor, "URL:") + "\n" + indent + s.URL)
return builder.String()
}
type StatusList struct { type StatusList struct {
Name string Name string
Statuses []Status Statuses []Status
} }
func (s StatusList) Display(noColor bool) string {
var builder strings.Builder
separator := strings.Repeat("─", 80)
builder.WriteString(utilities.HeaderFormat(noColor, s.Name) + "\n")
for _, status := range s.Statuses {
builder.WriteString("\n" + utilities.FullDisplayNameFormat(noColor, status.Account.DisplayName, status.Account.Acct) + "\n")
statusID := status.ID
createdAt := status.CreatedAt
if status.Reblog != nil {
builder.WriteString("reposted this status from " + utilities.FullDisplayNameFormat(noColor, status.Reblog.Account.DisplayName, status.Reblog.Account.Acct) + "\n")
statusID = status.Reblog.ID
createdAt = status.Reblog.CreatedAt
}
builder.WriteString(utilities.WrapLines(utilities.ConvertHTMLToText(status.Content), "\n", 80))
if status.Poll != nil {
displayPollContent(&builder, *status.Poll, noColor, "")
}
builder.WriteString(
"\n\n" +
utilities.FieldFormat(noColor, "Status ID:") + " " + statusID + "\t" +
utilities.FieldFormat(noColor, "Created at:") + " " + utilities.FormatTime(createdAt) +
"\n",
)
builder.WriteString(separator + "\n")
}
return builder.String()
}

View file

@ -1 +1,108 @@
package printer package printer
import (
"strconv"
"strings"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
)
func (p Printer) PrintAccount(account model.Account) {
var builder strings.Builder
builder.WriteString("\n" + p.fullDisplayNameFormat(account.DisplayName, account.Acct))
builder.WriteString("\n\n" + p.headerFormat("ACCOUNT ID:"))
builder.WriteString("\n" + account.ID)
builder.WriteString("\n\n" + p.headerFormat("JOINED ON:"))
builder.WriteString("\n" + p.formatDate(account.CreatedAt))
builder.WriteString("\n\n" + p.headerFormat("STATS:"))
builder.WriteString("\n" + p.fieldFormat("Followers:"))
builder.WriteString(" " + strconv.Itoa(account.FollowersCount))
builder.WriteString("\n" + p.fieldFormat("Following:"))
builder.WriteString(" " + strconv.Itoa(account.FollowingCount))
builder.WriteString("\n" + p.fieldFormat("Statuses:"))
builder.WriteString(" " + strconv.Itoa(account.StatusCount))
builder.WriteString("\n\n" + p.headerFormat("BIOGRAPHY:"))
builder.WriteString(utilities.WrapLines(utilities.ConvertHTMLToText(account.Note), "\n", p.maxTerminalWidth))
builder.WriteString("\n\n" + p.headerFormat("METADATA:"))
for _, field := range account.Fields {
builder.WriteString("\n" + p.fieldFormat(field.Name) + ": " + field.Value)
}
builder.WriteString("\n\n" + p.headerFormat("ACCOUNT URL:"))
builder.WriteString("\n" + account.URL + "\n")
printToStdout(builder.String())
}
func (p Printer) PrintAccountList(list model.AccountList) {
var builder strings.Builder
builder.WriteString("\n")
switch list.Type {
case model.AccountListFollowers:
builder.WriteString(p.headerFormat("Followed by:"))
case model.AccountListFollowing:
builder.WriteString(p.headerFormat("Following:"))
case model.AccountListBlockedAccount:
builder.WriteString(p.headerFormat("Blocked accounts:"))
case model.AccountListFollowRequests:
builder.WriteString(p.headerFormat("Accounts that have requested to follow you:"))
default:
builder.WriteString(p.headerFormat("Accounts:"))
}
if list.Type == model.AccountListBlockedAccount {
for ind := range list.Accounts {
builder.WriteString("\n" + p.bullet + " " + list.Accounts[ind].Acct + " (" + list.Accounts[ind].ID + ")")
}
} else {
for ind := range list.Accounts {
builder.WriteString("\n" + p.bullet + " " + p.fullDisplayNameFormat(list.Accounts[ind].DisplayName, list.Accounts[ind].Acct))
}
}
builder.WriteString("\n")
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())
}

View file

@ -9,7 +9,7 @@ import (
func (p Printer) PrintList(list model.List) { func (p Printer) PrintList(list model.List) {
var builder strings.Builder var builder strings.Builder
builder.WriteString(p.headerFormat("\n" + "LIST TITLE:") + "\n") builder.WriteString("\n" + p.headerFormat("LIST TITLE:") + "\n")
builder.WriteString(list.Title + "\n\n") builder.WriteString(list.Title + "\n\n")
builder.WriteString(p.headerFormat("LIST ID:") + "\n") builder.WriteString(p.headerFormat("LIST ID:") + "\n")
builder.WriteString(list.ID + "\n\n") builder.WriteString(list.ID + "\n\n")
@ -19,7 +19,7 @@ func (p Printer) PrintList(list model.List) {
if len(list.Accounts) > 0 { if len(list.Accounts) > 0 {
for acct, name := range list.Accounts { for acct, name := range list.Accounts {
builder.WriteString("\n" + p.bullet + p.fullDisplayNameFormat(name, acct)) builder.WriteString("\n" + p.bullet + " " + p.fullDisplayNameFormat(name, acct))
} }
} else { } else {
builder.WriteString("\n" + "None") builder.WriteString("\n" + "None")

62
internal/printer/poll.go Normal file
View file

@ -0,0 +1,62 @@
package printer
import (
"math"
"strconv"
"strings"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
)
func (p Printer) pollContent(poll model.Poll) string {
var builder strings.Builder
for ind, option := range poll.Options {
var (
votage float64
percentage int
)
if poll.VotesCount == 0 {
percentage = 0
} else {
votage = float64(option.VotesCount) / float64(poll.VotesCount)
percentage = int(math.Floor(100 * votage))
}
builder.WriteString("\n\n" + "[" + strconv.Itoa(ind) + "] " + option.Title)
builder.WriteString(p.pollMeter(votage))
builder.WriteString("\n" + strconv.Itoa(option.VotesCount) + " votes " + "(" + strconv.Itoa(percentage) + "%)")
}
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))
return builder.String()
}
func (p Printer) pollMeter(votage float64) string {
numVoteBlocks := int(math.Floor(float64(p.maxTerminalWidth) * votage))
numBackgroundBlocks := p.maxTerminalWidth - numVoteBlocks
voteBlockColor := p.theme.boldgreen
backgroundBlockColor := p.theme.grey
if p.noColor {
voteBlockColor = p.theme.reset
if numVoteBlocks == 0 {
numVoteBlocks = 1
}
}
meter := "\n" + voteBlockColor + strings.Repeat(p.pollMeterSymbol, numVoteBlocks) + p.theme.reset
if !p.noColor {
meter += backgroundBlockColor + strings.Repeat(p.pollMeterSymbol, numBackgroundBlocks) + p.theme.reset
}
return meter
}

View file

@ -6,6 +6,7 @@ package printer
import ( import (
"os" "os"
"os/exec"
"regexp" "regexp"
"strings" "strings"
"time" "time"
@ -16,6 +17,8 @@ type theme struct {
boldblue string boldblue string
boldmagenta string boldmagenta string
green string green string
boldgreen string
grey string
} }
type Printer struct { type Printer struct {
@ -42,13 +45,15 @@ func NewPrinter(
boldblue: "\033[34;1m", boldblue: "\033[34;1m",
boldmagenta: "\033[35;1m", boldmagenta: "\033[35;1m",
green: "\033[32m", green: "\033[32m",
boldgreen: "\033[32;1m",
grey: "\033[90m",
} }
return &Printer{ return &Printer{
noColor: noColor, noColor: noColor,
maxTerminalWidth: maxTerminalWidth, maxTerminalWidth: maxTerminalWidth,
pager: pager, pager: pager,
statusSeparator: strings.Repeat("─", maxTerminalWidth), statusSeparator: strings.Repeat("\u2501", maxTerminalWidth),
bullet: "\u2022", bullet: "\u2022",
pollMeterSymbol: "\u2501", pollMeterSymbol: "\u2501",
successSymbol: "\u2714", successSymbol: "\u2714",
@ -117,6 +122,43 @@ func (p Printer) formatDateTime(date time.Time) string {
return date.Local().Format(p.dateTimeFormat) return date.Local().Format(p.dateTimeFormat)
} }
func (p Printer) print(text string) {
if p.pager == "" {
printToStdout(text)
return
}
cmdSplit := strings.Split(p.pager, " ")
pager := new(exec.Cmd)
if len(cmdSplit) == 1 {
pager = exec.Command(cmdSplit[0]) //nolint:gosec
} else {
pager = exec.Command(cmdSplit[0], cmdSplit[1:]...) //nolint:gosec
}
pipe, err := pager.StdinPipe()
if err != nil {
printToStdout(text)
return
}
pager.Stdout = os.Stdout
pager.Stderr = os.Stderr
_ = pager.Start()
defer func() {
_ = pipe.Close()
_ = pager.Wait()
}()
_, _ = pipe.Write([]byte(text))
}
func printToStdout(text string) { func printToStdout(text string) {
os.Stdout.WriteString(text) os.Stdout.WriteString(text)
} }

View file

@ -0,0 +1,93 @@
package printer
import (
"strconv"
"strings"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
)
func (p Printer) PrintStatus(status model.Status) {
var builder strings.Builder
// The account information
builder.WriteString("\n" + p.fullDisplayNameFormat(status.Account.DisplayName, status.Account.Acct))
// The content of the status.
builder.WriteString("\n\n" + p.headerFormat("CONTENT:"))
builder.WriteString(utilities.WrapLines(utilities.ConvertHTMLToText(status.Content), "\n", p.maxTerminalWidth))
// If a poll exists in a status, write the contents to the builder.
if status.Poll != nil {
builder.WriteString(p.pollContent(*status.Poll))
}
// The ID of the status
builder.WriteString("\n\n" + p.headerFormat("STATUS ID:"))
builder.WriteString("\n" + status.ID)
// Status creation time
builder.WriteString("\n\n" + p.headerFormat("CREATED AT:"))
builder.WriteString("\n" + p.formatDateTime(status.CreatedAt))
// Status stats
builder.WriteString("\n\n" + p.headerFormat("STATS:"))
builder.WriteString("\n" + p.fieldFormat("Boosts: ") + strconv.Itoa(status.ReblogsCount))
builder.WriteString("\n" + p.fieldFormat("Likes: ") + strconv.Itoa(status.FavouritesCount))
builder.WriteString("\n" + p.fieldFormat("Replies: ") + strconv.Itoa(status.RepliesCount))
// Status visibility
builder.WriteString("\n\n" + p.headerFormat("VISIBILITY:"))
builder.WriteString("\n" + status.Visibility.String())
// Status URL
builder.WriteString("\n\n" + p.headerFormat("URL:"))
builder.WriteString("\n" + status.URL)
builder.WriteString("\n\n")
p.print(builder.String())
}
func (p Printer) PrintStatusList(list model.StatusList) {
var builder strings.Builder
builder.WriteString(p.headerFormat(list.Name) + "\n")
for _, status := range list.Statuses {
builder.WriteString("\n" + p.fullDisplayNameFormat(status.Account.DisplayName, status.Account.Acct))
statusID := status.ID
createdAt := status.CreatedAt
if status.Reblog != nil {
builder.WriteString(utilities.WrapLines(
"\n"+
"reposted this status from "+
p.fullDisplayNameFormat(status.Reblog.Account.DisplayName, status.Reblog.Account.Acct),
"\n",
p.maxTerminalWidth,
))
statusID = status.Reblog.ID
createdAt = status.Reblog.CreatedAt
}
builder.WriteString(utilities.WrapLines(utilities.ConvertHTMLToText(status.Content), "\n", p.maxTerminalWidth))
if status.Poll != nil {
builder.WriteString(p.pollContent(*status.Poll))
}
builder.WriteString(
"\n\n" +
p.fieldFormat("Status ID:") + " " + statusID + "\t" +
p.fieldFormat("Created at:") + " " + utilities.FormatTime(createdAt) +
"\n",
)
builder.WriteString(p.statusSeparator + "\n")
}
p.print(builder.String())
}