Compare commits
1 commit
09cd13a2f7
...
fcc08c1eb4
Author | SHA1 | Date | |
---|---|---|---|
fcc08c1eb4 |
10 changed files with 233 additions and 335 deletions
|
@ -109,16 +109,7 @@ func (a *AddExecutor) addAccountsToList(gtsClient *client.Client) error {
|
|||
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)
|
||||
}
|
||||
|
||||
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]}
|
||||
return fmt.Errorf("unable to get the account ID for %s, %w", a.accountNames[ind], err)
|
||||
}
|
||||
|
||||
accountIDs[ind] = accountID
|
||||
|
|
|
@ -94,11 +94,3 @@ func (e NoPollOptionError) Error() string {
|
|||
flagPollOption +
|
||||
" flag to add options to the poll"
|
||||
}
|
||||
|
||||
type NotFollowingError struct {
|
||||
Account string
|
||||
}
|
||||
|
||||
func (e NotFollowingError) Error() string {
|
||||
return "you are not following " + e.Account
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
s.printer.PrintAccount(account)
|
||||
utilities.Display(account, false, "")
|
||||
|
||||
if !s.myAccount && !s.skipAccountRelationship {
|
||||
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)
|
||||
}
|
||||
|
||||
s.printer.PrintAccountRelationship(relationship)
|
||||
utilities.Display(relationship, false, "")
|
||||
}
|
||||
|
||||
if s.myAccount && s.showUserPreferences {
|
||||
|
@ -171,7 +171,7 @@ func (s *ShowExecutor) showStatus(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
s.printer.PrintStatus(status)
|
||||
utilities.Display(status, false, "")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ func (s *ShowExecutor) showTimeline(gtsClient *client.Client) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
s.printer.PrintStatusList(timeline)
|
||||
utilities.Display(timeline, false, "")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error {
|
|||
}
|
||||
|
||||
if len(followers.Accounts) > 0 {
|
||||
s.printer.PrintAccountList(followers)
|
||||
utilities.Display(followers, false, "")
|
||||
} else {
|
||||
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 {
|
||||
s.printer.PrintAccountList(following)
|
||||
utilities.Display(following, false, "")
|
||||
} else {
|
||||
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 {
|
||||
s.printer.PrintAccountList(blocked)
|
||||
utilities.Display(blocked, false, "")
|
||||
} else {
|
||||
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 {
|
||||
s.printer.PrintStatusList(bookmarks)
|
||||
utilities.Display(bookmarks, false, "")
|
||||
} else {
|
||||
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 {
|
||||
s.printer.PrintStatusList(liked)
|
||||
utilities.Display(liked, false, "")
|
||||
} else {
|
||||
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 {
|
||||
s.printer.PrintAccountList(accounts)
|
||||
utilities.Display(accounts, false, "")
|
||||
} else {
|
||||
s.printer.PrintInfo("You have no follow requests.\n")
|
||||
}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
|
@ -60,6 +63,59 @@ type Field struct {
|
|||
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 {
|
||||
ID string `json:"id"`
|
||||
PrivateNote string `json:"note"`
|
||||
|
@ -77,6 +133,53 @@ type AccountRelationship struct {
|
|||
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
|
||||
|
||||
const (
|
||||
|
@ -90,3 +193,36 @@ type AccountList struct {
|
|||
Type AccountListType
|
||||
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
|
||||
}
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
||||
)
|
||||
|
||||
type Status struct {
|
||||
|
@ -135,7 +139,86 @@ type MediaDimensions struct {
|
|||
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 {
|
||||
Name string
|
||||
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()
|
||||
}
|
||||
|
|
|
@ -1,108 +1 @@
|
|||
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())
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
func (p Printer) PrintList(list model.List) {
|
||||
var builder strings.Builder
|
||||
|
||||
builder.WriteString("\n" + p.headerFormat("LIST TITLE:") + "\n")
|
||||
builder.WriteString(p.headerFormat("\n" + "LIST TITLE:") + "\n")
|
||||
builder.WriteString(list.Title + "\n\n")
|
||||
builder.WriteString(p.headerFormat("LIST ID:") + "\n")
|
||||
builder.WriteString(list.ID + "\n\n")
|
||||
|
@ -19,7 +19,7 @@ func (p Printer) PrintList(list model.List) {
|
|||
|
||||
if len(list.Accounts) > 0 {
|
||||
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 {
|
||||
builder.WriteString("\n" + "None")
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
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
|
||||
}
|
|
@ -6,7 +6,6 @@ package printer
|
|||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -17,8 +16,6 @@ type theme struct {
|
|||
boldblue string
|
||||
boldmagenta string
|
||||
green string
|
||||
boldgreen string
|
||||
grey string
|
||||
}
|
||||
|
||||
type Printer struct {
|
||||
|
@ -45,15 +42,13 @@ func NewPrinter(
|
|||
boldblue: "\033[34;1m",
|
||||
boldmagenta: "\033[35;1m",
|
||||
green: "\033[32m",
|
||||
boldgreen: "\033[32;1m",
|
||||
grey: "\033[90m",
|
||||
}
|
||||
|
||||
return &Printer{
|
||||
noColor: noColor,
|
||||
maxTerminalWidth: maxTerminalWidth,
|
||||
pager: pager,
|
||||
statusSeparator: strings.Repeat("\u2501", maxTerminalWidth),
|
||||
statusSeparator: strings.Repeat("─", maxTerminalWidth),
|
||||
bullet: "\u2022",
|
||||
pollMeterSymbol: "\u2501",
|
||||
successSymbol: "\u2714",
|
||||
|
@ -122,43 +117,6 @@ func (p Printer) formatDateTime(date time.Time) string {
|
|||
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) {
|
||||
os.Stdout.WriteString(text)
|
||||
}
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
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())
|
||||
}
|
Loading…
Reference in a new issue