Compare commits
4 commits
fcc08c1eb4
...
09cd13a2f7
Author | SHA1 | Date | |
---|---|---|---|
09cd13a2f7 | |||
d842233c98 | |||
947b1b8c46 | |||
f73f1f5872 |
23 changed files with 746 additions and 442 deletions
|
@ -11,6 +11,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/executor"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/executor"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -87,39 +88,52 @@ func run() error {
|
||||||
command := flag.Arg(0)
|
command := flag.Arg(0)
|
||||||
args := flag.Args()[1:]
|
args := flag.Args()[1:]
|
||||||
|
|
||||||
|
enbasPrinter := printer.NewPrinter(
|
||||||
|
*topLevelFlags.NoColor,
|
||||||
|
topLevelFlags.Pager,
|
||||||
|
80,
|
||||||
|
)
|
||||||
|
|
||||||
executorMap := map[string]executor.Executor{
|
executorMap := map[string]executor.Executor{
|
||||||
executor.CommandAccept: executor.NewAcceptOrRejectExecutor(
|
executor.CommandAccept: executor.NewAcceptOrRejectExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandAccept,
|
executor.CommandAccept,
|
||||||
executor.CommandSummaryLookup(executor.CommandAccept),
|
executor.CommandSummaryLookup(executor.CommandAccept),
|
||||||
),
|
),
|
||||||
executor.CommandAdd: executor.NewAddExecutor(
|
executor.CommandAdd: executor.NewAddExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandAdd,
|
executor.CommandAdd,
|
||||||
executor.CommandSummaryLookup(executor.CommandAdd),
|
executor.CommandSummaryLookup(executor.CommandAdd),
|
||||||
),
|
),
|
||||||
executor.CommandBlock: executor.NewBlockOrUnblockExecutor(
|
executor.CommandBlock: executor.NewBlockOrUnblockExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandBlock,
|
executor.CommandBlock,
|
||||||
executor.CommandSummaryLookup(executor.CommandBlock),
|
executor.CommandSummaryLookup(executor.CommandBlock),
|
||||||
),
|
),
|
||||||
executor.CommandCreate: executor.NewCreateExecutor(
|
executor.CommandCreate: executor.NewCreateExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandCreate,
|
executor.CommandCreate,
|
||||||
executor.CommandSummaryLookup(executor.CommandCreate),
|
executor.CommandSummaryLookup(executor.CommandCreate),
|
||||||
),
|
),
|
||||||
executor.CommandDelete: executor.NewDeleteExecutor(
|
executor.CommandDelete: executor.NewDeleteExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandDelete,
|
executor.CommandDelete,
|
||||||
executor.CommandSummaryLookup(executor.CommandDelete),
|
executor.CommandSummaryLookup(executor.CommandDelete),
|
||||||
),
|
),
|
||||||
executor.CommandEdit: executor.NewEditExecutor(
|
executor.CommandEdit: executor.NewEditExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandEdit,
|
executor.CommandEdit,
|
||||||
executor.CommandSummaryLookup(executor.CommandEdit),
|
executor.CommandSummaryLookup(executor.CommandEdit),
|
||||||
),
|
),
|
||||||
executor.CommandFollow: executor.NewFollowOrUnfollowExecutor(
|
executor.CommandFollow: executor.NewFollowOrUnfollowExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandFollow,
|
executor.CommandFollow,
|
||||||
executor.CommandSummaryLookup(executor.CommandFollow),
|
executor.CommandSummaryLookup(executor.CommandFollow),
|
||||||
),
|
),
|
||||||
|
@ -129,7 +143,8 @@ func run() error {
|
||||||
executor.CommandSummaryLookup(executor.CommandLogin),
|
executor.CommandSummaryLookup(executor.CommandLogin),
|
||||||
),
|
),
|
||||||
executor.CommandReject: executor.NewAcceptOrRejectExecutor(
|
executor.CommandReject: executor.NewAcceptOrRejectExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandReject,
|
executor.CommandReject,
|
||||||
executor.CommandSummaryLookup(executor.CommandReject),
|
executor.CommandSummaryLookup(executor.CommandReject),
|
||||||
),
|
),
|
||||||
|
@ -139,26 +154,31 @@ func run() error {
|
||||||
executor.CommandSummaryLookup(executor.CommandRemove),
|
executor.CommandSummaryLookup(executor.CommandRemove),
|
||||||
),
|
),
|
||||||
executor.CommandSwitch: executor.NewSwitchExecutor(
|
executor.CommandSwitch: executor.NewSwitchExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandSwitch,
|
executor.CommandSwitch,
|
||||||
executor.CommandSummaryLookup(executor.CommandSwitch),
|
executor.CommandSummaryLookup(executor.CommandSwitch),
|
||||||
),
|
),
|
||||||
executor.CommandUnfollow: executor.NewFollowOrUnfollowExecutor(
|
executor.CommandUnfollow: executor.NewFollowOrUnfollowExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandUnfollow,
|
executor.CommandUnfollow,
|
||||||
executor.CommandSummaryLookup(executor.CommandUnfollow),
|
executor.CommandSummaryLookup(executor.CommandUnfollow),
|
||||||
),
|
),
|
||||||
executor.CommandUnblock: executor.NewBlockOrUnblockExecutor(
|
executor.CommandUnblock: executor.NewBlockOrUnblockExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandUnblock,
|
executor.CommandUnblock,
|
||||||
executor.CommandSummaryLookup(executor.CommandUnblock),
|
executor.CommandSummaryLookup(executor.CommandUnblock),
|
||||||
),
|
),
|
||||||
executor.CommandShow: executor.NewShowExecutor(
|
executor.CommandShow: executor.NewShowExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandShow,
|
executor.CommandShow,
|
||||||
executor.CommandSummaryLookup(executor.CommandShow),
|
executor.CommandSummaryLookup(executor.CommandShow),
|
||||||
),
|
),
|
||||||
executor.CommandVersion: executor.NewVersionExecutor(
|
executor.CommandVersion: executor.NewVersionExecutor(
|
||||||
|
enbasPrinter,
|
||||||
executor.CommandVersion,
|
executor.CommandVersion,
|
||||||
executor.CommandSummaryLookup(executor.CommandVersion),
|
executor.CommandSummaryLookup(executor.CommandVersion),
|
||||||
binaryVersion,
|
binaryVersion,
|
||||||
|
@ -167,7 +187,8 @@ func run() error {
|
||||||
gitCommit,
|
gitCommit,
|
||||||
),
|
),
|
||||||
executor.CommandWhoami: executor.NewWhoAmIExecutor(
|
executor.CommandWhoami: executor.NewWhoAmIExecutor(
|
||||||
topLevelFlags,
|
enbasPrinter,
|
||||||
|
topLevelFlags.ConfigDir,
|
||||||
executor.CommandWhoami,
|
executor.CommandWhoami,
|
||||||
executor.CommandSummaryLookup(executor.CommandWhoami),
|
executor.CommandSummaryLookup(executor.CommandWhoami),
|
||||||
),
|
),
|
||||||
|
|
|
@ -17,7 +17,7 @@ const (
|
||||||
listPath string = "/api/v1/lists"
|
listPath string = "/api/v1/lists"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *Client) GetAllLists() (model.Lists, error) {
|
func (g *Client) GetAllLists() ([]model.List, error) {
|
||||||
url := g.Authentication.Instance + listPath
|
url := g.Authentication.Instance + listPath
|
||||||
|
|
||||||
var lists []model.List
|
var lists []model.List
|
||||||
|
|
|
@ -9,22 +9,25 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AcceptOrRejectExecutor struct {
|
type AcceptOrRejectExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
printer *printer.Printer
|
||||||
|
configDir string
|
||||||
resourceType string
|
resourceType string
|
||||||
accountName string
|
accountName string
|
||||||
command string
|
command string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAcceptOrRejectExecutor(tlf TopLevelFlags, name, summary string) *AcceptOrRejectExecutor {
|
func NewAcceptOrRejectExecutor(enbasPrinter *printer.Printer, configDir, name, summary string) *AcceptOrRejectExecutor {
|
||||||
acceptExe := AcceptOrRejectExecutor{
|
acceptExe := AcceptOrRejectExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
|
|
||||||
topLevelFlags: tlf,
|
printer: enbasPrinter,
|
||||||
|
configDir: configDir,
|
||||||
command: name,
|
command: name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +49,7 @@ func (a *AcceptOrRejectExecutor) Execute() error {
|
||||||
return UnsupportedTypeError{resourceType: a.resourceType}
|
return UnsupportedTypeError{resourceType: a.resourceType}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsClient, err := client.NewClientFromConfig(a.topLevelFlags.ConfigDir)
|
gtsClient, err := client.NewClientFromConfig(a.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -55,7 +58,7 @@ func (a *AcceptOrRejectExecutor) Execute() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AcceptOrRejectExecutor) acceptOrRejectFollowRequest(gtsClient *client.Client) error {
|
func (a *AcceptOrRejectExecutor) acceptOrRejectFollowRequest(gtsClient *client.Client) error {
|
||||||
accountID, err := getAccountID(gtsClient, false, a.accountName, a.topLevelFlags.ConfigDir)
|
accountID, err := getAccountID(gtsClient, false, a.accountName, a.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -75,7 +78,7 @@ func (a *AcceptOrRejectExecutor) acceptFollowRequest(gtsClient *client.Client, a
|
||||||
return fmt.Errorf("unable to accept the follow request: %w", err)
|
return fmt.Errorf("unable to accept the follow request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully accepted the follow request.")
|
a.printer.PrintSuccess("Successfully accepted the follow request.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -85,7 +88,7 @@ func (a *AcceptOrRejectExecutor) rejectFollowRequest(gtsClient *client.Client, a
|
||||||
return fmt.Errorf("unable to reject the follow request: %w", err)
|
return fmt.Errorf("unable to reject the follow request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully rejected the follow request.")
|
a.printer.PrintSuccess("Successfully rejected the follow request.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddExecutor struct {
|
type AddExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
printer *printer.Printer
|
||||||
|
configDir string
|
||||||
resourceType string
|
resourceType string
|
||||||
toResourceType string
|
toResourceType string
|
||||||
listID string
|
listID string
|
||||||
|
@ -26,13 +28,15 @@ type AddExecutor struct {
|
||||||
content string
|
content string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAddExecutor(tlf TopLevelFlags, name, summary string) *AddExecutor {
|
func NewAddExecutor(printer *printer.Printer, configDir, name, summary string) *AddExecutor {
|
||||||
emptyArr := make([]string, 0, 3)
|
emptyArr := make([]string, 0, 3)
|
||||||
|
|
||||||
addExe := AddExecutor{
|
addExe := AddExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
|
|
||||||
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
accountNames: MultiStringFlagValue(emptyArr),
|
accountNames: MultiStringFlagValue(emptyArr),
|
||||||
topLevelFlags: tlf,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addExe.StringVar(&addExe.resourceType, flagType, "", "Specify the resource type to add (e.g. account, note)")
|
addExe.StringVar(&addExe.resourceType, flagType, "", "Specify the resource type to add (e.g. account, note)")
|
||||||
|
@ -67,7 +71,7 @@ func (a *AddExecutor) Execute() error {
|
||||||
return UnsupportedTypeError{resourceType: a.toResourceType}
|
return UnsupportedTypeError{resourceType: a.toResourceType}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsClient, err := client.NewClientFromConfig(a.topLevelFlags.ConfigDir)
|
gtsClient, err := client.NewClientFromConfig(a.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -105,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
|
||||||
|
@ -115,7 +128,7 @@ func (a *AddExecutor) addAccountsToList(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to add the accounts to the list: %w", err)
|
return fmt.Errorf("unable to add the accounts to the list: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully added the account(s) to the list.")
|
a.printer.PrintSuccess("Successfully added the account(s) to the list.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -141,7 +154,7 @@ func (a *AddExecutor) addNoteToAccount(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unexpected number of accounts specified: want 1, got %d", len(a.accountNames))
|
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)
|
accountID, err := getAccountID(gtsClient, false, a.accountNames[0], a.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -157,7 +170,7 @@ func (a *AddExecutor) addNoteToAccount(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to add the private note to the account: %w", err)
|
return fmt.Errorf("unable to add the private note to the account: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully added the private note to the account.")
|
a.printer.PrintSuccess("Successfully added the private note to the account.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -187,7 +200,7 @@ func (a *AddExecutor) addStatusToBookmarks(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to add the status to your bookmarks: %w", err)
|
return fmt.Errorf("unable to add the status to your bookmarks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully added the status to your bookmarks.")
|
a.printer.PrintSuccess("Successfully added the status to your bookmarks.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -219,7 +232,7 @@ func (a *AddExecutor) addStarToStatus(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to add the %s to the status: %w", a.resourceType, err)
|
return fmt.Errorf("unable to add the %s to the status: %w", a.resourceType, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Successfully added a %s to the status.\n", a.resourceType)
|
a.printer.PrintSuccess("Successfully added a " + a.resourceType + " to the status.\n")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -229,7 +242,7 @@ func (a *AddExecutor) addBoostToStatus(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to add the boost to the status: %w", err)
|
return fmt.Errorf("unable to add the boost to the status: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully added the boost to the status.")
|
a.printer.PrintSuccess("Successfully added the boost to the status.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -276,7 +289,7 @@ func (a *AddExecutor) addVoteToPoll(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to add your vote(s) to the poll: %w", err)
|
return fmt.Errorf("unable to add your vote(s) to the poll: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully added your vote(s) to the poll.")
|
a.printer.PrintSuccess("Successfully added your vote(s) to the poll.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,22 +9,25 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BlockOrUnblockExecutor struct {
|
type BlockOrUnblockExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
printer *printer.Printer
|
||||||
|
configDir string
|
||||||
resourceType string
|
resourceType string
|
||||||
accountName string
|
accountName string
|
||||||
command string
|
command string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBlockOrUnblockExecutor(tlf TopLevelFlags, name, summary string) *BlockOrUnblockExecutor {
|
func NewBlockOrUnblockExecutor(printer *printer.Printer, configDir, name, summary string) *BlockOrUnblockExecutor {
|
||||||
blockExe := BlockOrUnblockExecutor{
|
blockExe := BlockOrUnblockExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
|
|
||||||
topLevelFlags: tlf,
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
command: name,
|
command: name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +49,7 @@ func (b *BlockOrUnblockExecutor) Execute() error {
|
||||||
return UnsupportedTypeError{resourceType: b.resourceType}
|
return UnsupportedTypeError{resourceType: b.resourceType}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsClient, err := client.NewClientFromConfig(b.topLevelFlags.ConfigDir)
|
gtsClient, err := client.NewClientFromConfig(b.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -55,7 +58,7 @@ func (b *BlockOrUnblockExecutor) Execute() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BlockOrUnblockExecutor) blockOrUnblockAccount(gtsClient *client.Client) error {
|
func (b *BlockOrUnblockExecutor) blockOrUnblockAccount(gtsClient *client.Client) error {
|
||||||
accountID, err := getAccountID(gtsClient, false, b.accountName, b.topLevelFlags.ConfigDir)
|
accountID, err := getAccountID(gtsClient, false, b.accountName, b.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -75,7 +78,7 @@ func (b *BlockOrUnblockExecutor) blockAccount(gtsClient *client.Client, accountI
|
||||||
return fmt.Errorf("unable to block the account: %w", err)
|
return fmt.Errorf("unable to block the account: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully blocked the account.")
|
b.printer.PrintSuccess("Successfully blocked the account.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -85,7 +88,7 @@ func (b *BlockOrUnblockExecutor) unblockAccount(gtsClient *client.Client, accoun
|
||||||
return fmt.Errorf("unable to unblock the account: %w", err)
|
return fmt.Errorf("unable to unblock the account: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully unblocked the account.")
|
b.printer.PrintSuccess("Successfully unblocked the account.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,14 @@ import (
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateExecutor struct {
|
type CreateExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
printer *printer.Printer
|
||||||
addPoll bool
|
addPoll bool
|
||||||
boostable bool
|
boostable bool
|
||||||
federated bool
|
federated bool
|
||||||
|
@ -26,6 +27,7 @@ type CreateExecutor struct {
|
||||||
pollHidesVoteCounts bool
|
pollHidesVoteCounts bool
|
||||||
replyable bool
|
replyable bool
|
||||||
sensitive *bool
|
sensitive *bool
|
||||||
|
configDir string
|
||||||
content string
|
content string
|
||||||
contentType string
|
contentType string
|
||||||
fromFile string
|
fromFile string
|
||||||
|
@ -39,11 +41,12 @@ type CreateExecutor struct {
|
||||||
pollOptions MultiStringFlagValue
|
pollOptions MultiStringFlagValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCreateExecutor(tlf TopLevelFlags, name, summary string) *CreateExecutor {
|
func NewCreateExecutor(printer *printer.Printer, configDir, name, summary string) *CreateExecutor {
|
||||||
createExe := CreateExecutor{
|
createExe := CreateExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
|
|
||||||
topLevelFlags: tlf,
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
createExe.BoolVar(&createExe.boostable, flagEnableReposts, true, "Specify if the status can be reposted/boosted by others")
|
createExe.BoolVar(&createExe.boostable, flagEnableReposts, true, "Specify if the status can be reposted/boosted by others")
|
||||||
|
@ -87,7 +90,7 @@ func (c *CreateExecutor) Execute() error {
|
||||||
return FlagNotSetError{flagText: flagType}
|
return FlagNotSetError{flagText: flagType}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsClient, err := client.NewClientFromConfig(c.topLevelFlags.ConfigDir)
|
gtsClient, err := client.NewClientFromConfig(c.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -125,8 +128,8 @@ func (c *CreateExecutor) createList(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to create the list: %w", err)
|
return fmt.Errorf("unable to create the list: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully created the following list:")
|
c.printer.PrintSuccess("Successfully created the following list:")
|
||||||
utilities.Display(list, *c.topLevelFlags.NoColor, c.topLevelFlags.Pager)
|
c.printer.PrintList(list)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -217,13 +220,13 @@ func (c *CreateExecutor) createStatus(gtsClient *client.Client) error {
|
||||||
form.Poll = &poll
|
form.Poll = &poll
|
||||||
}
|
}
|
||||||
|
|
||||||
status, err := gtsClient.CreateStatus(form)
|
_, err = gtsClient.CreateStatus(form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the status: %w", err)
|
return fmt.Errorf("unable to create the status: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully created the following status:")
|
c.printer.PrintSuccess("Successfully created the following status:")
|
||||||
utilities.Display(status, *c.topLevelFlags.NoColor, c.topLevelFlags.Pager)
|
//utilities.Display(status, *c.topLevelFlags.NoColor, c.topLevelFlags.Pager)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,20 +9,24 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeleteExecutor struct {
|
type DeleteExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
printer *printer.Printer
|
||||||
|
configDir string
|
||||||
resourceType string
|
resourceType string
|
||||||
listID string
|
listID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeleteExecutor(tlf TopLevelFlags, name, summary string) *DeleteExecutor {
|
func NewDeleteExecutor(printer *printer.Printer, configDir, name, summary string) *DeleteExecutor {
|
||||||
deleteExe := DeleteExecutor{
|
deleteExe := DeleteExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
topLevelFlags: tlf,
|
|
||||||
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteExe.StringVar(&deleteExe.resourceType, flagType, "", "Specify the type of resource to delete")
|
deleteExe.StringVar(&deleteExe.resourceType, flagType, "", "Specify the type of resource to delete")
|
||||||
|
@ -47,7 +51,7 @@ func (d *DeleteExecutor) Execute() error {
|
||||||
return UnsupportedTypeError{resourceType: d.resourceType}
|
return UnsupportedTypeError{resourceType: d.resourceType}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsClient, err := client.NewClientFromConfig(d.topLevelFlags.ConfigDir)
|
gtsClient, err := client.NewClientFromConfig(d.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -64,7 +68,7 @@ func (d *DeleteExecutor) deleteList(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to delete the list: %w", err)
|
return fmt.Errorf("unable to delete the list: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("The list was successfully deleted.")
|
d.printer.PrintSuccess("The list was successfully deleted.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,23 +10,26 @@ import (
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EditExecutor struct {
|
type EditExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
printer *printer.Printer
|
||||||
|
configDir string
|
||||||
resourceType string
|
resourceType string
|
||||||
listID string
|
listID string
|
||||||
listTitle string
|
listTitle string
|
||||||
listRepliesPolicy string
|
listRepliesPolicy string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEditExecutor(tlf TopLevelFlags, name, summary string) *EditExecutor {
|
func NewEditExecutor(printer *printer.Printer, configDir, name, summary string) *EditExecutor {
|
||||||
editExe := EditExecutor{
|
editExe := EditExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
topLevelFlags: tlf,
|
|
||||||
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
editExe.StringVar(&editExe.resourceType, flagType, "", "Specify the type of resource to update")
|
editExe.StringVar(&editExe.resourceType, flagType, "", "Specify the type of resource to update")
|
||||||
|
@ -53,7 +56,7 @@ func (e *EditExecutor) Execute() error {
|
||||||
return UnsupportedTypeError{resourceType: e.resourceType}
|
return UnsupportedTypeError{resourceType: e.resourceType}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsClient, err := client.NewClientFromConfig(e.topLevelFlags.ConfigDir)
|
gtsClient, err := client.NewClientFromConfig(e.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -89,8 +92,8 @@ func (e *EditExecutor) editList(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to update the list: %w", err)
|
return fmt.Errorf("unable to update the list: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully updated the list.")
|
e.printer.PrintSuccess("Successfully updated the list.")
|
||||||
utilities.Display(updatedList, *e.topLevelFlags.NoColor, e.topLevelFlags.Pager)
|
e.printer.PrintList(updatedList)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -9,12 +9,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FollowOrUnfollowExecutor struct {
|
type FollowOrUnfollowExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
printer *printer.Printer
|
||||||
|
configDir string
|
||||||
resourceType string
|
resourceType string
|
||||||
accountName string
|
accountName string
|
||||||
showReposts bool
|
showReposts bool
|
||||||
|
@ -22,11 +24,12 @@ type FollowOrUnfollowExecutor struct {
|
||||||
action string
|
action string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFollowOrUnfollowExecutor(tlf TopLevelFlags, name, summary string) *FollowOrUnfollowExecutor {
|
func NewFollowOrUnfollowExecutor(printer *printer.Printer, configDir, name, summary string) *FollowOrUnfollowExecutor {
|
||||||
command := FollowOrUnfollowExecutor{
|
command := FollowOrUnfollowExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
|
|
||||||
topLevelFlags: tlf,
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
action: name,
|
action: name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +53,7 @@ func (f *FollowOrUnfollowExecutor) Execute() error {
|
||||||
return UnsupportedTypeError{resourceType: f.resourceType}
|
return UnsupportedTypeError{resourceType: f.resourceType}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsClient, err := client.NewClientFromConfig(f.topLevelFlags.ConfigDir)
|
gtsClient, err := client.NewClientFromConfig(f.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -59,7 +62,7 @@ func (f *FollowOrUnfollowExecutor) Execute() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FollowOrUnfollowExecutor) followOrUnfollowAccount(gtsClient *client.Client) error {
|
func (f *FollowOrUnfollowExecutor) followOrUnfollowAccount(gtsClient *client.Client) error {
|
||||||
accountID, err := getAccountID(gtsClient, false, f.accountName, f.topLevelFlags.ConfigDir)
|
accountID, err := getAccountID(gtsClient, false, f.accountName, f.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -85,7 +88,7 @@ func (f *FollowOrUnfollowExecutor) followAccount(gtsClient *client.Client, accou
|
||||||
return fmt.Errorf("unable to follow the account: %w", err)
|
return fmt.Errorf("unable to follow the account: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("The follow request was sent successfully.")
|
f.printer.PrintSuccess("Successfully sent the follow request.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -95,7 +98,7 @@ func (f *FollowOrUnfollowExecutor) unfollowAccount(gtsClient *client.Client, acc
|
||||||
return fmt.Errorf("unable to unfollow the account: %w", err)
|
return fmt.Errorf("unable to unfollow the account: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully unfollowed the account.")
|
f.printer.PrintSuccess("Successfully unfollowed the account.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,19 @@ import (
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ShowExecutor struct {
|
type ShowExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
topLevelFlags TopLevelFlags
|
|
||||||
|
printer *printer.Printer
|
||||||
myAccount bool
|
myAccount bool
|
||||||
skipAccountRelationship bool
|
skipAccountRelationship bool
|
||||||
showUserPreferences bool
|
showUserPreferences bool
|
||||||
showInBrowser bool
|
showInBrowser bool
|
||||||
|
configDir string
|
||||||
resourceType string
|
resourceType string
|
||||||
accountName string
|
accountName string
|
||||||
statusID string
|
statusID string
|
||||||
|
@ -30,10 +33,12 @@ type ShowExecutor struct {
|
||||||
limit int
|
limit int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewShowExecutor(tlf TopLevelFlags, name, summary string) *ShowExecutor {
|
func NewShowExecutor(printer *printer.Printer, configDir, name, summary string) *ShowExecutor {
|
||||||
showExe := ShowExecutor{
|
showExe := ShowExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
topLevelFlags: tlf,
|
|
||||||
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
showExe.BoolVar(&showExe.myAccount, flagMyAccount, false, "Set to true to lookup your account")
|
showExe.BoolVar(&showExe.myAccount, flagMyAccount, false, "Set to true to lookup your account")
|
||||||
|
@ -80,7 +85,7 @@ func (s *ShowExecutor) Execute() error {
|
||||||
return UnsupportedTypeError{resourceType: s.resourceType}
|
return UnsupportedTypeError{resourceType: s.resourceType}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsClient, err := client.NewClientFromConfig(s.topLevelFlags.ConfigDir)
|
gtsClient, err := client.NewClientFromConfig(s.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +99,7 @@ func (s *ShowExecutor) showInstance(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to retrieve the instance details: %w", err)
|
return fmt.Errorf("unable to retrieve the instance details: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities.Display(instance, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
utilities.Display(instance, false, "")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -106,7 +111,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
if s.myAccount {
|
if s.myAccount {
|
||||||
account, err = getMyAccount(gtsClient, s.topLevelFlags.ConfigDir)
|
account, err = getMyAccount(gtsClient, s.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("received an error while getting the account details: %w", err)
|
return fmt.Errorf("received an error while getting the account details: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -127,7 +132,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities.Display(account, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
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)
|
||||||
|
@ -135,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, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintAccountRelationship(relationship)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.myAccount && s.showUserPreferences {
|
if s.myAccount && s.showUserPreferences {
|
||||||
|
@ -144,7 +149,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to retrieve the user preferences: %w", err)
|
return fmt.Errorf("unable to retrieve the user preferences: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities.Display(preferences, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
utilities.Display(preferences, false, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -166,7 +171,7 @@ func (s *ShowExecutor) showStatus(gtsClient *client.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities.Display(status, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintStatus(status)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -210,12 +215,12 @@ func (s *ShowExecutor) showTimeline(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(timeline.Statuses) == 0 {
|
if len(timeline.Statuses) == 0 {
|
||||||
fmt.Println("There are no statuses in this timeline.")
|
s.printer.PrintInfo("There are no statuses in this timeline.\n")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities.Display(timeline, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintStatusList(timeline)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -244,7 +249,7 @@ func (s *ShowExecutor) showList(gtsClient *client.Client) error {
|
||||||
list.Accounts = accountMap
|
list.Accounts = accountMap
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities.Display(list, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintList(list)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -256,18 +261,18 @@ func (s *ShowExecutor) showLists(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(lists) == 0 {
|
if len(lists) == 0 {
|
||||||
fmt.Println("You have no lists.")
|
s.printer.PrintInfo("You have no lists.\n")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities.Display(lists, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintLists(lists)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error {
|
func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error {
|
||||||
accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.topLevelFlags.ConfigDir)
|
accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -278,16 +283,16 @@ func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(followers.Accounts) > 0 {
|
if len(followers.Accounts) > 0 {
|
||||||
utilities.Display(followers, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintAccountList(followers)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("There are no followers for this account or the list is hidden.")
|
s.printer.PrintInfo("There are no followers for this account (or the list is hidden).\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ShowExecutor) showFollowing(gtsClient *client.Client) error {
|
func (s *ShowExecutor) showFollowing(gtsClient *client.Client) error {
|
||||||
accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.topLevelFlags.ConfigDir)
|
accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
return fmt.Errorf("received an error while getting the account ID: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -298,9 +303,9 @@ func (s *ShowExecutor) showFollowing(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(following.Accounts) > 0 {
|
if len(following.Accounts) > 0 {
|
||||||
utilities.Display(following, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintAccountList(following)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("This account is not following anyone or the list is hidden.")
|
s.printer.PrintInfo("This account is not following anyone or the list is hidden.\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -313,9 +318,9 @@ func (s *ShowExecutor) showBlocked(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(blocked.Accounts) > 0 {
|
if len(blocked.Accounts) > 0 {
|
||||||
utilities.Display(blocked, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintAccountList(blocked)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("You have no blocked accounts.")
|
s.printer.PrintInfo("You have no blocked accounts.\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -328,9 +333,9 @@ func (s *ShowExecutor) showBookmarks(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(bookmarks.Statuses) > 0 {
|
if len(bookmarks.Statuses) > 0 {
|
||||||
utilities.Display(bookmarks, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintStatusList(bookmarks)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("You have no bookmarks.")
|
s.printer.PrintInfo("You have no bookmarks.\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -343,9 +348,9 @@ func (s *ShowExecutor) showLiked(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(liked.Statuses) > 0 {
|
if len(liked.Statuses) > 0 {
|
||||||
utilities.Display(liked, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintStatusList(liked)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("You have no %s statuses.\n", s.resourceType)
|
s.printer.PrintInfo("You have no " + s.resourceType + " statuses.\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -358,9 +363,9 @@ func (s *ShowExecutor) showFollowRequests(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(accounts.Accounts) > 0 {
|
if len(accounts.Accounts) > 0 {
|
||||||
utilities.Display(accounts, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
s.printer.PrintAccountList(accounts)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("You have no follow requests.")
|
s.printer.PrintInfo("You have no follow requests.\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -376,7 +381,7 @@ func (s *ShowExecutor) showPoll(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to retrieve the poll: %w", err)
|
return fmt.Errorf("unable to retrieve the poll: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
utilities.Display(poll, *s.topLevelFlags.NoColor, s.topLevelFlags.Pager)
|
utilities.Display(poll, false, "")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,20 +9,23 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SwitchExecutor struct {
|
type SwitchExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
configDir string
|
||||||
toResourceType string
|
toResourceType string
|
||||||
accountName string
|
accountName string
|
||||||
|
printer *printer.Printer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSwitchExecutor(tlf TopLevelFlags, name, summary string) *SwitchExecutor {
|
func NewSwitchExecutor(printer *printer.Printer, configDir, name, summary string) *SwitchExecutor {
|
||||||
switchExe := SwitchExecutor{
|
switchExe := SwitchExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
topLevelFlags: tlf,
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
switchExe.StringVar(&switchExe.toResourceType, flagTo, "", "The account to switch to")
|
switchExe.StringVar(&switchExe.toResourceType, flagTo, "", "The account to switch to")
|
||||||
|
@ -51,11 +54,11 @@ func (s *SwitchExecutor) switchToAccount() error {
|
||||||
return NoAccountSpecifiedError{}
|
return NoAccountSpecifiedError{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := config.UpdateCurrentAccount(s.accountName, s.topLevelFlags.ConfigDir); err != nil {
|
if err := config.UpdateCurrentAccount(s.accountName, s.configDir); err != nil {
|
||||||
return fmt.Errorf("unable to switch account to the account: %w", err)
|
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)
|
s.printer.PrintSuccess("The current account is now set to '" + s.accountName + "'.")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,13 @@ package executor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"os"
|
|
||||||
"strings"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
"text/tabwriter"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type VersionExecutor struct {
|
type VersionExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
printer *printer.Printer
|
||||||
showFullVersion bool
|
showFullVersion bool
|
||||||
binaryVersion string
|
binaryVersion string
|
||||||
buildTime string
|
buildTime string
|
||||||
|
@ -20,9 +20,19 @@ type VersionExecutor struct {
|
||||||
gitCommit string
|
gitCommit string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVersionExecutor(name, summary, binaryVersion, buildTime, goVersion, gitCommit string) *VersionExecutor {
|
func NewVersionExecutor(
|
||||||
|
enbasPrinter *printer.Printer,
|
||||||
|
name,
|
||||||
|
summary,
|
||||||
|
binaryVersion,
|
||||||
|
buildTime,
|
||||||
|
goVersion,
|
||||||
|
gitCommit string,
|
||||||
|
) *VersionExecutor {
|
||||||
command := VersionExecutor{
|
command := VersionExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
|
|
||||||
|
printer: enbasPrinter,
|
||||||
binaryVersion: binaryVersion,
|
binaryVersion: binaryVersion,
|
||||||
buildTime: buildTime,
|
buildTime: buildTime,
|
||||||
goVersion: goVersion,
|
goVersion: goVersion,
|
||||||
|
@ -38,24 +48,7 @@ func NewVersionExecutor(name, summary, binaryVersion, buildTime, goVersion, gitC
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VersionExecutor) Execute() error {
|
func (v *VersionExecutor) Execute() error {
|
||||||
var builder strings.Builder
|
v.printer.PrintVersion(v.showFullVersion, v.binaryVersion, v.buildTime, v.goVersion, v.gitCommit)
|
||||||
|
|
||||||
if v.showFullVersion {
|
|
||||||
builder.WriteString("Enbas\n")
|
|
||||||
|
|
||||||
tableWriter := tabwriter.NewWriter(&builder, 0, 8, 0, '\t', 0)
|
|
||||||
|
|
||||||
tableWriter.Write([]byte(" Version:\t" + v.binaryVersion + "\n"))
|
|
||||||
tableWriter.Write([]byte(" Git commit:\t" + v.gitCommit + "\n"))
|
|
||||||
tableWriter.Write([]byte(" Go version:\t" + v.goVersion + "\n"))
|
|
||||||
tableWriter.Write([]byte(" Build date:\t" + v.buildTime + "\n"))
|
|
||||||
|
|
||||||
tableWriter.Flush()
|
|
||||||
} else {
|
|
||||||
builder.WriteString("Enbas " + v.binaryVersion + "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Stdout.WriteString(builder.String())
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,18 +9,22 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WhoAmIExecutor struct {
|
type WhoAmIExecutor struct {
|
||||||
*flag.FlagSet
|
*flag.FlagSet
|
||||||
|
|
||||||
topLevelFlags TopLevelFlags
|
printer *printer.Printer
|
||||||
|
configDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWhoAmIExecutor(tlf TopLevelFlags, name, summary string) *WhoAmIExecutor {
|
func NewWhoAmIExecutor(printer *printer.Printer, configDir, name, summary string) *WhoAmIExecutor {
|
||||||
whoExe := WhoAmIExecutor{
|
whoExe := WhoAmIExecutor{
|
||||||
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
||||||
topLevelFlags: tlf,
|
|
||||||
|
printer: printer,
|
||||||
|
configDir: configDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
whoExe.Usage = commandUsageFunc(name, summary, whoExe.FlagSet)
|
whoExe.Usage = commandUsageFunc(name, summary, whoExe.FlagSet)
|
||||||
|
@ -29,12 +33,12 @@ func NewWhoAmIExecutor(tlf TopLevelFlags, name, summary string) *WhoAmIExecutor
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *WhoAmIExecutor) Execute() error {
|
func (c *WhoAmIExecutor) Execute() error {
|
||||||
config, err := config.NewCredentialsConfigFromFile(c.topLevelFlags.ConfigDir)
|
config, err := config.NewCredentialsConfigFromFile(c.configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to load the credential config: %w", err)
|
return fmt.Errorf("unable to load the credential config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("You are logged in as %q.\n", config.CurrentAccount)
|
c.printer.PrintInfo("You are logged in as '" + config.CurrentAccount + "'.\n")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,8 +7,6 @@ package model
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ListRepliesPolicy int
|
type ListRepliesPolicy int
|
||||||
|
@ -107,53 +105,3 @@ type List struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Accounts map[string]string
|
Accounts map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l List) Display(noColor bool) string {
|
|
||||||
format := `
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s`
|
|
||||||
|
|
||||||
output := fmt.Sprintf(
|
|
||||||
format,
|
|
||||||
utilities.HeaderFormat(noColor, "LIST TITLE:"), l.Title,
|
|
||||||
utilities.HeaderFormat(noColor, "LIST ID:"), l.ID,
|
|
||||||
utilities.HeaderFormat(noColor, "REPLIES POLICY:"), l.RepliesPolicy,
|
|
||||||
utilities.HeaderFormat(noColor, "ADDED ACCOUNTS:"),
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(l.Accounts) > 0 {
|
|
||||||
for acct, name := range l.Accounts {
|
|
||||||
output += "\n • " + utilities.FullDisplayNameFormat(noColor, name, acct)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
output += "\n None"
|
|
||||||
}
|
|
||||||
|
|
||||||
output += "\n"
|
|
||||||
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
type Lists []List
|
|
||||||
|
|
||||||
func (l Lists) Display(noColor bool) string {
|
|
||||||
output := "\n" + utilities.HeaderFormat(noColor, "LISTS")
|
|
||||||
|
|
||||||
for i := range l {
|
|
||||||
output += fmt.Sprintf(
|
|
||||||
"\n • %s (%s)",
|
|
||||||
l[i].Title,
|
|
||||||
l[i].ID,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
|
||||||
|
|
108
internal/printer/account.go
Normal file
108
internal/printer/account.go
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
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())
|
||||||
|
}
|
45
internal/printer/list.go
Normal file
45
internal/printer/list.go
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
package printer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p Printer) PrintList(list model.List) {
|
||||||
|
var builder strings.Builder
|
||||||
|
|
||||||
|
builder.WriteString("\n" + p.headerFormat("LIST TITLE:") + "\n")
|
||||||
|
builder.WriteString(list.Title + "\n\n")
|
||||||
|
builder.WriteString(p.headerFormat("LIST ID:") + "\n")
|
||||||
|
builder.WriteString(list.ID + "\n\n")
|
||||||
|
builder.WriteString(p.headerFormat("REPLIES POLICY:") + "\n")
|
||||||
|
builder.WriteString(list.RepliesPolicy.String() + "\n\n")
|
||||||
|
builder.WriteString(p.headerFormat("ADDED ACCOUNTS:"))
|
||||||
|
|
||||||
|
if len(list.Accounts) > 0 {
|
||||||
|
for acct, name := range list.Accounts {
|
||||||
|
builder.WriteString("\n" + p.bullet + " " + p.fullDisplayNameFormat(name, acct))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder.WriteString("\n" + "None")
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.WriteString("\n")
|
||||||
|
|
||||||
|
printToStdout(builder.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) PrintLists(lists []model.List) {
|
||||||
|
var builder strings.Builder
|
||||||
|
|
||||||
|
builder.WriteString("\n" + p.headerFormat("LISTS"))
|
||||||
|
|
||||||
|
for i := range lists {
|
||||||
|
builder.WriteString("\n" + p.bullet + " " + lists[i].Title + " (" + lists[i].ID + ")")
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.WriteString("\n")
|
||||||
|
|
||||||
|
printToStdout(builder.String())
|
||||||
|
}
|
62
internal/printer/poll.go
Normal file
62
internal/printer/poll.go
Normal 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
|
||||||
|
}
|
168
internal/printer/printer.go
Normal file
168
internal/printer/printer.go
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Dan Anglin <d.n.i.anglin@gmail.com>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package printer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type theme struct {
|
||||||
|
reset string
|
||||||
|
boldblue string
|
||||||
|
boldmagenta string
|
||||||
|
green string
|
||||||
|
boldgreen string
|
||||||
|
grey string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Printer struct {
|
||||||
|
theme theme
|
||||||
|
noColor bool
|
||||||
|
maxTerminalWidth int
|
||||||
|
pager string
|
||||||
|
statusSeparator string
|
||||||
|
bullet string
|
||||||
|
pollMeterSymbol string
|
||||||
|
successSymbol string
|
||||||
|
failureSymbol string
|
||||||
|
dateFormat string
|
||||||
|
dateTimeFormat string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPrinter(
|
||||||
|
noColor bool,
|
||||||
|
pager string,
|
||||||
|
maxTerminalWidth int,
|
||||||
|
) *Printer {
|
||||||
|
theme := theme{
|
||||||
|
reset: "\033[0m",
|
||||||
|
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),
|
||||||
|
bullet: "\u2022",
|
||||||
|
pollMeterSymbol: "\u2501",
|
||||||
|
successSymbol: "\u2714",
|
||||||
|
failureSymbol: "\u2717",
|
||||||
|
dateFormat: "02 Jan 2006",
|
||||||
|
dateTimeFormat: "02 Jan 2006, 15:04 (MST)",
|
||||||
|
theme: theme,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) PrintSuccess(text string) {
|
||||||
|
success := p.theme.green + p.successSymbol + p.theme.reset
|
||||||
|
if p.noColor {
|
||||||
|
success = p.successSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
printToStdout(success + " " + text + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) PrintFailure(text string) {
|
||||||
|
printToStderr(p.failureSymbol + " " + text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) PrintInfo(text string) {
|
||||||
|
printToStdout(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) headerFormat(text string) string {
|
||||||
|
if p.noColor {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.theme.boldblue + text + p.theme.reset
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) fieldFormat(text string) string {
|
||||||
|
if p.noColor {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.theme.green + text + p.theme.reset
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) fullDisplayNameFormat(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 p.noColor {
|
||||||
|
builder.WriteString(pattern.ReplaceAllString(displayName, ""))
|
||||||
|
} else {
|
||||||
|
builder.WriteString(p.theme.boldmagenta + pattern.ReplaceAllString(displayName, "") + p.theme.reset)
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.WriteString(" (@" + acct + ")")
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) formatDate(date time.Time) string {
|
||||||
|
return date.Local().Format(p.dateFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printToStderr(text string) {
|
||||||
|
os.Stderr.WriteString(text)
|
||||||
|
}
|
93
internal/printer/status.go
Normal file
93
internal/printer/status.go
Normal 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())
|
||||||
|
}
|
33
internal/printer/version.go
Normal file
33
internal/printer/version.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Dan Anglin <d.n.i.anglin@gmail.com>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package printer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"text/tabwriter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p Printer) PrintVersion(showFullVersion bool, binaryVersion, buildTime, goVersion, gitCommit string) {
|
||||||
|
if !showFullVersion {
|
||||||
|
printToStdout("Enbas " + binaryVersion + "\n")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder strings.Builder
|
||||||
|
|
||||||
|
builder.WriteString(p.headerFormat("Enbas") + "\n\n")
|
||||||
|
|
||||||
|
tableWriter := tabwriter.NewWriter(&builder, 0, 4, 1, ' ', 0)
|
||||||
|
|
||||||
|
_, _ = tableWriter.Write([]byte(p.fieldFormat("Version:") + "\t" + binaryVersion + "\n"))
|
||||||
|
_, _ = tableWriter.Write([]byte(p.fieldFormat("Git commit:") + "\t" + gitCommit + "\n"))
|
||||||
|
_, _ = tableWriter.Write([]byte(p.fieldFormat("Go version:") + "\t" + goVersion + "\n"))
|
||||||
|
_, _ = tableWriter.Write([]byte(p.fieldFormat("Build date:") + "\t" + buildTime + "\n"))
|
||||||
|
|
||||||
|
tableWriter.Flush()
|
||||||
|
|
||||||
|
printToStdout(builder.String())
|
||||||
|
}
|
Loading…
Reference in a new issue