enbas/internal/executor/show.go

345 lines
9.3 KiB
Go

// SPDX-FileCopyrightText: 2024 Dan Anglin <d.n.i.anglin@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-or-later
package executor
import (
"flag"
"fmt"
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
"codeflow.dananglin.me.uk/apollo/enbas/internal/utilities"
)
type ShowExecutor struct {
*flag.FlagSet
topLevelFlags TopLevelFlags
myAccount bool
skipAccountRelationship bool
showUserPreferences bool
showInBrowser bool
resourceType string
accountName string
statusID string
timelineCategory string
listID string
tag string
limit int
}
func NewShowExecutor(tlf TopLevelFlags, name, summary string) *ShowExecutor {
showExe := ShowExecutor{
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
topLevelFlags: tlf,
}
showExe.BoolVar(&showExe.myAccount, flagMyAccount, false, "set to true to lookup your account")
showExe.BoolVar(&showExe.skipAccountRelationship, flagSkipRelationship, false, "set to true to skip showing your relationship to the specified account")
showExe.BoolVar(&showExe.showUserPreferences, flagShowPreferences, false, "show your preferences")
showExe.BoolVar(&showExe.showInBrowser, flagBrowser, false, "set to true to view in the browser")
showExe.StringVar(&showExe.resourceType, flagType, "", "specify the type of resource to display")
showExe.StringVar(&showExe.accountName, flagAccountName, "", "specify the account name in full (username@domain)")
showExe.StringVar(&showExe.statusID, flagStatusID, "", "specify the ID of the status to display")
showExe.StringVar(&showExe.timelineCategory, flagTimelineCategory, model.TimelineCategoryHome, "specify the timeline category to view")
showExe.StringVar(&showExe.listID, flagListID, "", "specify the ID of the list to display")
showExe.StringVar(&showExe.tag, flagTag, "", "specify the name of the tag to use")
showExe.IntVar(&showExe.limit, flagLimit, 20, "specify the limit of items to display")
showExe.Usage = commandUsageFunc(name, summary, showExe.FlagSet)
return &showExe
}
func (s *ShowExecutor) Execute() error {
if s.resourceType == "" {
return FlagNotSetError{flagText: flagType}
}
funcMap := map[string]func(*client.Client) error{
resourceInstance: s.showInstance,
resourceAccount: s.showAccount,
resourceStatus: s.showStatus,
resourceTimeline: s.showTimeline,
resourceList: s.showList,
resourceFollowers: s.showFollowers,
resourceFollowing: s.showFollowing,
resourceBlocked: s.showBlocked,
resourceBookmarks: s.showBookmarks,
resourceNotification: s.showNotifications,
}
doFunc, ok := funcMap[s.resourceType]
if !ok {
return UnsupportedTypeError{resourceType: s.resourceType}
}
gtsClient, err := client.NewClientFromConfig(s.topLevelFlags.ConfigDir)
if err != nil {
return fmt.Errorf("unable to create the GoToSocial client: %w", err)
}
return doFunc(gtsClient)
}
func (s *ShowExecutor) showInstance(gtsClient *client.Client) error {
instance, err := gtsClient.GetInstance()
if err != nil {
return fmt.Errorf("unable to retrieve the instance details: %w", err)
}
utilities.Display(instance, *s.topLevelFlags.NoColor)
return nil
}
func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
var (
account model.Account
err error
)
if s.myAccount {
account, err = getMyAccount(gtsClient, s.topLevelFlags.ConfigDir)
if err != nil {
return fmt.Errorf("received an error while getting the account details: %w", err)
}
} else {
if s.accountName == "" {
return FlagNotSetError{flagText: flagAccountName}
}
account, err = getAccount(gtsClient, s.accountName)
if err != nil {
return fmt.Errorf("received an error while getting the account details: %w", err)
}
}
if s.showInBrowser {
utilities.OpenLink(account.URL)
return nil
}
utilities.Display(account, *s.topLevelFlags.NoColor)
if !s.myAccount && !s.skipAccountRelationship {
relationship, err := gtsClient.GetAccountRelationship(account.ID)
if err != nil {
return fmt.Errorf("unable to retrieve the relationship to this account: %w", err)
}
utilities.Display(relationship, *s.topLevelFlags.NoColor)
}
if s.myAccount && s.showUserPreferences {
preferences, err := gtsClient.GetUserPreferences()
if err != nil {
return fmt.Errorf("unable to retrieve the user preferences: %w", err)
}
utilities.Display(preferences, *s.topLevelFlags.NoColor)
}
return nil
}
func (s *ShowExecutor) showStatus(gtsClient *client.Client) error {
if s.statusID == "" {
return FlagNotSetError{flagText: flagStatusID}
}
status, err := gtsClient.GetStatus(s.statusID)
if err != nil {
return fmt.Errorf("unable to retrieve the status: %w", err)
}
if s.showInBrowser {
utilities.OpenLink(status.URL)
return nil
}
utilities.Display(status, *s.topLevelFlags.NoColor)
return nil
}
func (s *ShowExecutor) showTimeline(gtsClient *client.Client) error {
var (
timeline model.StatusList
err error
)
switch s.timelineCategory {
case model.TimelineCategoryHome:
timeline, err = gtsClient.GetHomeTimeline(s.limit)
case model.TimelineCategoryPublic:
timeline, err = gtsClient.GetPublicTimeline(s.limit)
case model.TimelineCategoryList:
if s.listID == "" {
return FlagNotSetError{flagText: flagListID}
}
var list model.List
list, err = gtsClient.GetList(s.listID)
if err != nil {
return fmt.Errorf("unable to retrieve the list: %w", err)
}
timeline, err = gtsClient.GetListTimeline(list.ID, list.Title, s.limit)
case model.TimelineCategoryTag:
if s.tag == "" {
return FlagNotSetError{flagText: flagTag}
}
timeline, err = gtsClient.GetTagTimeline(s.tag, s.limit)
default:
return model.InvalidTimelineCategoryError{Value: s.timelineCategory}
}
if err != nil {
return fmt.Errorf("unable to retrieve the %s timeline: %w", s.timelineCategory, err)
}
if len(timeline.Statuses) == 0 {
fmt.Println("There are no statuses in this timeline.")
return nil
}
utilities.Display(timeline, *s.topLevelFlags.NoColor)
return nil
}
func (s *ShowExecutor) showList(gtsClient *client.Client) error {
if s.listID == "" {
return s.showLists(gtsClient)
}
list, err := gtsClient.GetList(s.listID)
if err != nil {
return fmt.Errorf("unable to retrieve the list: %w", err)
}
accounts, err := gtsClient.GetAccountsFromList(s.listID, 0)
if err != nil {
return fmt.Errorf("unable to retrieve the accounts from the list: %w", err)
}
if len(accounts) > 0 {
accountMap := make(map[string]string)
for i := range accounts {
accountMap[accounts[i].Acct] = accounts[i].Username
}
list.Accounts = accountMap
}
utilities.Display(list, *s.topLevelFlags.NoColor)
return nil
}
func (s *ShowExecutor) showLists(gtsClient *client.Client) error {
lists, err := gtsClient.GetAllLists()
if err != nil {
return fmt.Errorf("unable to retrieve the lists: %w", err)
}
if len(lists) == 0 {
fmt.Println("You have no lists.")
return nil
}
utilities.Display(lists, *s.topLevelFlags.NoColor)
return nil
}
func (s *ShowExecutor) showFollowers(gtsClient *client.Client) error {
accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.topLevelFlags.ConfigDir)
if err != nil {
return fmt.Errorf("received an error while getting the account ID: %w", err)
}
followers, err := gtsClient.GetFollowers(accountID, s.limit)
if err != nil {
return fmt.Errorf("unable to retrieve the list of followers: %w", err)
}
if len(followers.Accounts) > 0 {
utilities.Display(followers, *s.topLevelFlags.NoColor)
} else {
fmt.Println("There are no followers for this account or the list is hidden.")
}
return nil
}
func (s *ShowExecutor) showFollowing(gtsClient *client.Client) error {
accountID, err := getAccountID(gtsClient, s.myAccount, s.accountName, s.topLevelFlags.ConfigDir)
if err != nil {
return fmt.Errorf("received an error while getting the account ID: %w", err)
}
following, err := gtsClient.GetFollowing(accountID, s.limit)
if err != nil {
return fmt.Errorf("unable to retrieve the list of followed accounts: %w", err)
}
if len(following.Accounts) > 0 {
utilities.Display(following, *s.topLevelFlags.NoColor)
} else {
fmt.Println("This account is not following anyone or the list is hidden.")
}
return nil
}
func (s *ShowExecutor) showBlocked(gtsClient *client.Client) error {
blocked, err := gtsClient.GetBlockedAccounts(s.limit)
if err != nil {
return fmt.Errorf("unable to retrieve the list of blocked accounts: %w", err)
}
if len(blocked.Accounts) > 0 {
utilities.Display(blocked, *s.topLevelFlags.NoColor)
} else {
fmt.Println("You have no blocked accounts.")
}
return nil
}
func (s *ShowExecutor) showBookmarks(gtsClient *client.Client) error {
bookmarks, err := gtsClient.GetBookmarks(s.limit)
if err != nil {
return fmt.Errorf("unable to retrieve the list of bookmarks: %w", err)
}
if len(bookmarks.Statuses) > 0 {
utilities.Display(bookmarks, *s.topLevelFlags.NoColor)
} else {
fmt.Println("You have no bookmarks.")
}
return nil
}
func (s *ShowExecutor) showNotifications(gts *client.Client) error {
notifications, err := gts.GetNotifications(s.limit)
if err != nil {
return fmt.Errorf("unable to retrieve your notifications: %w", err)
}
for i := range notifications {
utilities.Display(notifications[i], *s.topLevelFlags.NoColor)
}
return nil
}