253 lines
4.7 KiB
Go
253 lines
4.7 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"strings"
|
|
"unicode"
|
|
|
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/client"
|
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/config"
|
|
"golang.org/x/net/html"
|
|
)
|
|
|
|
var instanceDetailsFormat = `INSTANCE:
|
|
%s - %s
|
|
|
|
DOMAIN:
|
|
%s
|
|
|
|
VERSION:
|
|
Running GoToSocial %s
|
|
|
|
CONTACT:
|
|
name: %s
|
|
username: %s
|
|
email: %s
|
|
`
|
|
|
|
var accountDetailsFormat = `
|
|
%s (@%s)
|
|
|
|
ACCOUNT ID:
|
|
%s
|
|
|
|
JOINED ON:
|
|
%s
|
|
|
|
STATS:
|
|
Followers: %d
|
|
Following: %d
|
|
Statuses: %d
|
|
|
|
BIOGRAPHY:
|
|
%s
|
|
|
|
METADATA: %s
|
|
|
|
ACCOUNT URL:
|
|
%s
|
|
`
|
|
|
|
var statusDetailsFormat = `
|
|
%s (@%s)
|
|
|
|
CONTENT:
|
|
%s
|
|
|
|
STATUS ID:
|
|
%s
|
|
|
|
CREATED AT:
|
|
%s
|
|
|
|
STATS:
|
|
Boosts: %d
|
|
Likes: %d
|
|
Replies: %d
|
|
|
|
VISIBILITY:
|
|
%s
|
|
|
|
URL:
|
|
%s
|
|
`
|
|
|
|
type showCommand struct {
|
|
*flag.FlagSet
|
|
myAccount bool
|
|
targetType string
|
|
account string
|
|
statusID string
|
|
}
|
|
|
|
func newShowCommand(name, summary string) *showCommand {
|
|
command := showCommand{
|
|
FlagSet: flag.NewFlagSet(name, flag.ExitOnError),
|
|
myAccount: false,
|
|
targetType: "",
|
|
account: "",
|
|
statusID: "",
|
|
}
|
|
|
|
command.BoolVar(&command.myAccount, "my-account", false, "set to true to lookup your account")
|
|
command.StringVar(&command.targetType, "type", "", "specify the type of resource to display")
|
|
command.StringVar(&command.account, "account", "", "specify the account URI to lookup")
|
|
command.StringVar(&command.statusID, "status-id", "", "specify the ID of the status to display")
|
|
command.Usage = commandUsageFunc(name, summary, command.FlagSet)
|
|
|
|
return &command
|
|
}
|
|
|
|
func (c *showCommand) Execute() error {
|
|
gtsClient, err := client.NewClientFromConfig()
|
|
if err != nil {
|
|
return fmt.Errorf("unable to create the GoToSocial client; %w", err)
|
|
}
|
|
|
|
funcMap := map[string]func(*client.Client) error{
|
|
"instance": c.showInstance,
|
|
"account": c.showAccount,
|
|
"status": c.showStatus,
|
|
}
|
|
|
|
doFunc, ok := funcMap[c.targetType]
|
|
if !ok {
|
|
return fmt.Errorf("unsupported type %q", c.targetType)
|
|
}
|
|
|
|
return doFunc(gtsClient)
|
|
}
|
|
|
|
func (c *showCommand) showInstance(gts *client.Client) error {
|
|
instance, err := gts.GetInstance()
|
|
if err != nil {
|
|
return fmt.Errorf("unable to retrieve the instance details; %w", err)
|
|
}
|
|
|
|
fmt.Printf(
|
|
instanceDetailsFormat,
|
|
instance.Title,
|
|
instance.Description,
|
|
instance.Domain,
|
|
instance.Version,
|
|
instance.Contact.Account.DisplayName,
|
|
instance.Contact.Account.Username,
|
|
instance.Contact.Email,
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *showCommand) showAccount(gts *client.Client) error {
|
|
var accountURI string
|
|
|
|
if c.myAccount {
|
|
authConfig, err := config.NewAuthenticationConfigFromFile()
|
|
if err != nil {
|
|
return fmt.Errorf("unable to retrieve the authentication configuration; %w", err)
|
|
}
|
|
|
|
accountURI = authConfig.CurrentAccount
|
|
} else {
|
|
if c.account == "" {
|
|
return errors.New("the account flag is not set")
|
|
}
|
|
|
|
accountURI = c.account
|
|
}
|
|
|
|
account, err := gts.GetAccount(accountURI)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to retrieve the account details; %w", err)
|
|
}
|
|
|
|
metadata := ""
|
|
|
|
for _, field := range account.Fields {
|
|
metadata += fmt.Sprintf("\n %s: %s", field.Name, stripHTMLTags(field.Value))
|
|
}
|
|
|
|
fmt.Printf(
|
|
accountDetailsFormat,
|
|
account.DisplayName,
|
|
account.Username,
|
|
account.ID,
|
|
account.CreatedAt.Format("02 Jan 2006"),
|
|
account.FollowersCount,
|
|
account.FollowingCount,
|
|
account.StatusCount,
|
|
wrapLine(stripHTMLTags(account.Note), "\n ", 80),
|
|
metadata,
|
|
account.URL,
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *showCommand) showStatus(gts *client.Client) error {
|
|
if c.statusID == "" {
|
|
return errors.New("the status-id flag is not set")
|
|
}
|
|
|
|
status, err := gts.GetStatus(c.statusID)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to retrieve the status; %w", err)
|
|
}
|
|
|
|
fmt.Printf(
|
|
statusDetailsFormat,
|
|
status.Account.DisplayName,
|
|
status.Account.Username,
|
|
stripHTMLTags(status.Content),
|
|
status.ID,
|
|
status.CreatedAt.Format("02 Jan 2006, 03:04"),
|
|
status.RebloggsCount,
|
|
status.FavouritesCount,
|
|
status.RepliesCount,
|
|
status.Visibility,
|
|
status.URL,
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
func stripHTMLTags(text string) string {
|
|
token := html.NewTokenizer(strings.NewReader(text))
|
|
|
|
var builder strings.Builder
|
|
|
|
for {
|
|
tt := token.Next()
|
|
switch tt {
|
|
case html.ErrorToken:
|
|
return builder.String()
|
|
case html.TextToken:
|
|
builder.WriteString(token.Token().Data + " ")
|
|
}
|
|
}
|
|
}
|
|
|
|
func wrapLine(line, separator string, charLimit int) string {
|
|
if len(line) <= charLimit {
|
|
return line
|
|
}
|
|
|
|
leftcursor, rightcursor := 0, 0
|
|
|
|
var builder strings.Builder
|
|
|
|
for rightcursor < (len(line) - charLimit) {
|
|
rightcursor += charLimit
|
|
for !unicode.IsSpace(rune(line[rightcursor-1])) {
|
|
rightcursor--
|
|
}
|
|
builder.WriteString(line[leftcursor:rightcursor] + separator)
|
|
leftcursor = rightcursor
|
|
}
|
|
|
|
builder.WriteString(line[rightcursor:])
|
|
|
|
return builder.String()
|
|
}
|