feat: view media attachment information
View media attachment information in the timeline and status views. Users can also show detailed information of the attachments via the attachment ID.
This commit is contained in:
parent
2a386fcda5
commit
e8114f8d22
7 changed files with 160 additions and 41 deletions
20
internal/client/media.go
Normal file
20
internal/client/media.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||
)
|
||||
|
||||
func (g *Client) GetMediaAttachment(mediaAttachmentID string) (model.Attachment, error) {
|
||||
url := g.Authentication.Instance + "/api/v1/media/" + mediaAttachmentID
|
||||
|
||||
var attachment model.Attachment
|
||||
|
||||
if err := g.sendRequest(http.MethodGet, url, nil, &attachment); err != nil {
|
||||
return model.Attachment{}, fmt.Errorf("received an error after sending the request to get the media attachment: %w", err)
|
||||
}
|
||||
|
||||
return attachment, nil
|
||||
}
|
|
@ -14,6 +14,7 @@ import (
|
|||
const (
|
||||
flagAddPoll = "add-poll"
|
||||
flagAccountName = "account-name"
|
||||
flagAttachmentID = "attachment-id"
|
||||
flagBrowser = "browser"
|
||||
flagChoose = "choose"
|
||||
flagContentType = "content-type"
|
||||
|
|
|
@ -16,6 +16,8 @@ const (
|
|||
resourceLike = "like"
|
||||
resourceLiked = "liked"
|
||||
resourceList = "list"
|
||||
resourceMedia = "media"
|
||||
resourceMediaAttachment = "media-attachment"
|
||||
resourceMutedAccounts = "muted-accounts"
|
||||
resourceNote = "note"
|
||||
resourcePoll = "poll"
|
||||
|
|
|
@ -30,6 +30,7 @@ type ShowExecutor struct {
|
|||
listID string
|
||||
tag string
|
||||
pollID string
|
||||
attachmentID string
|
||||
limit int
|
||||
}
|
||||
|
||||
|
@ -52,6 +53,7 @@ func NewShowExecutor(printer *printer.Printer, configDir, name, summary string)
|
|||
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.StringVar(&showExe.pollID, flagPollID, "", "Specify the ID of the poll to display")
|
||||
showExe.StringVar(&showExe.attachmentID, flagAttachmentID, "", "Specify the ID of the media attachment to display")
|
||||
showExe.IntVar(&showExe.limit, flagLimit, 20, "Specify the limit of items to display")
|
||||
|
||||
showExe.Usage = commandUsageFunc(name, summary, showExe.FlagSet)
|
||||
|
@ -79,6 +81,8 @@ func (s *ShowExecutor) Execute() error {
|
|||
resourceFollowRequest: s.showFollowRequests,
|
||||
resourcePoll: s.showPoll,
|
||||
resourceMutedAccounts: s.showMutedAccounts,
|
||||
resourceMedia: s.showMediaAttachment,
|
||||
resourceMediaAttachment: s.showMediaAttachment,
|
||||
}
|
||||
|
||||
doFunc, ok := funcMap[s.resourceType]
|
||||
|
@ -134,8 +138,8 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
|||
}
|
||||
|
||||
var (
|
||||
relationship *model.AccountRelationship = nil
|
||||
preferences *model.Preferences = nil
|
||||
relationship *model.AccountRelationship
|
||||
preferences *model.Preferences
|
||||
)
|
||||
|
||||
if !s.myAccount && !s.skipAccountRelationship {
|
||||
|
@ -402,3 +406,18 @@ func (s *ShowExecutor) showMutedAccounts(gtsClient *client.Client) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ShowExecutor) showMediaAttachment(gtsClient *client.Client) error {
|
||||
if s.attachmentID == "" {
|
||||
return FlagNotSetError{flagText: flagAttachmentID}
|
||||
}
|
||||
|
||||
attachment, err := gtsClient.GetMediaAttachment(s.attachmentID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to retrieve the media attachment: %w", err)
|
||||
}
|
||||
|
||||
s.printer.PrintMediaAttachment(attachment)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
45
internal/printer/media_attachment.go
Normal file
45
internal/printer/media_attachment.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package printer
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||
)
|
||||
|
||||
func (p Printer) PrintMediaAttachment(attachement model.Attachment) {
|
||||
var builder strings.Builder
|
||||
|
||||
// The ID of the media attachment
|
||||
builder.WriteString("\n" + p.headerFormat("MEDIA ATTACHMENT ID:"))
|
||||
builder.WriteString("\n" + attachement.ID)
|
||||
|
||||
// The media attachment type
|
||||
builder.WriteString("\n\n" + p.headerFormat("TYPE:"))
|
||||
builder.WriteString("\n" + attachement.Type)
|
||||
|
||||
// The description that came with the media attachment (if any)
|
||||
description := attachement.Description
|
||||
if description == "" {
|
||||
description = noMediaDescription
|
||||
}
|
||||
|
||||
builder.WriteString("\n\n" + p.headerFormat("DESCRIPTION:"))
|
||||
builder.WriteString("\n" + description)
|
||||
|
||||
// The original size of the media attachment
|
||||
builder.WriteString("\n\n" + p.headerFormat("ORIGINAL SIZE:"))
|
||||
builder.WriteString("\n" + attachement.Meta.Original.Size)
|
||||
|
||||
// The media attachment's focus
|
||||
builder.WriteString("\n\n" + p.headerFormat("FOCUS:"))
|
||||
builder.WriteString("\n" + p.fieldFormat("x:") + " " + strconv.FormatFloat(attachement.Meta.Focus.X, 'f', 1, 64))
|
||||
builder.WriteString("\n" + p.fieldFormat("y:") + " " + strconv.FormatFloat(attachement.Meta.Focus.Y, 'f', 1, 64))
|
||||
|
||||
// The URL to the source of the media attachment
|
||||
builder.WriteString("\n\n" + p.headerFormat("URL:"))
|
||||
builder.WriteString("\n" + attachement.URL)
|
||||
builder.WriteString("\n\n")
|
||||
|
||||
p.print(builder.String())
|
||||
}
|
|
@ -14,6 +14,7 @@ import (
|
|||
|
||||
const (
|
||||
minTerminalWidth = 40
|
||||
noMediaDescription = "This media attachment has no description."
|
||||
)
|
||||
|
||||
type theme struct {
|
||||
|
@ -39,6 +40,7 @@ type Printer struct {
|
|||
failureSymbol string
|
||||
dateFormat string
|
||||
dateTimeFormat string
|
||||
imageIcon string
|
||||
}
|
||||
|
||||
func NewPrinter(
|
||||
|
@ -62,6 +64,7 @@ func NewPrinter(
|
|||
}
|
||||
|
||||
return &Printer{
|
||||
theme: theme,
|
||||
noColor: noColor,
|
||||
maxTerminalWidth: maxTerminalWidth,
|
||||
pager: pager,
|
||||
|
@ -72,7 +75,7 @@ func NewPrinter(
|
|||
failureSymbol: "\u2717",
|
||||
dateFormat: "02 Jan 2006",
|
||||
dateTimeFormat: "02 Jan 2006, 15:04 (MST)",
|
||||
theme: theme,
|
||||
imageIcon: "\uf03e",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,19 +18,37 @@ func (p Printer) PrintStatus(status model.Status) {
|
|||
// The account information
|
||||
builder.WriteString("\n" + p.fullDisplayNameFormat(status.Account.DisplayName, status.Account.Acct))
|
||||
|
||||
// The ID of the status
|
||||
builder.WriteString("\n\n" + p.headerFormat("STATUS ID:"))
|
||||
builder.WriteString("\n" + status.ID)
|
||||
|
||||
// The content of the status.
|
||||
builder.WriteString("\n\n" + p.headerFormat("CONTENT:"))
|
||||
builder.WriteString(utilities.WrapLines(utilities.ConvertHTMLToText(status.Content), "\n", p.maxTerminalWidth))
|
||||
|
||||
// Details of media attachments (if any).
|
||||
if len(status.MediaAttachments) > 0 {
|
||||
builder.WriteString("\n\n" + p.headerFormat("MEDIA ATTACHMENTS:"))
|
||||
|
||||
for ind, media := range status.MediaAttachments {
|
||||
builder.WriteString("\n\n[" + strconv.Itoa(ind) + "] " + p.fieldFormat("ID:") + " " + media.ID)
|
||||
builder.WriteString("\n " + p.fieldFormat("Type:") + " " + media.Type)
|
||||
|
||||
description := media.Description
|
||||
if description == "" {
|
||||
description = noMediaDescription
|
||||
}
|
||||
|
||||
builder.WriteString("\n " + p.fieldFormat("Description:") + " " + description)
|
||||
builder.WriteString("\n " + p.fieldFormat("Media URL:") + " " + media.URL)
|
||||
}
|
||||
}
|
||||
|
||||
// If a poll exists in a status, write the contents to the builder.
|
||||
if status.Poll != nil {
|
||||
builder.WriteString(p.pollOptions(*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))
|
||||
|
@ -79,6 +97,17 @@ func (p Printer) PrintStatusList(list model.StatusList) {
|
|||
builder.WriteString(p.pollOptions(*status.Poll))
|
||||
}
|
||||
|
||||
for _, media := range status.MediaAttachments {
|
||||
builder.WriteString("\n\n" + p.imageIcon + " Media (" + media.ID + ")" + "\n ")
|
||||
|
||||
description := media.Description
|
||||
if description == "" {
|
||||
description = noMediaDescription
|
||||
}
|
||||
|
||||
builder.WriteString(utilities.WrapLines(description, "\n ", p.maxTerminalWidth-3))
|
||||
}
|
||||
|
||||
builder.WriteString(
|
||||
"\n\n" +
|
||||
p.fieldFormat("Status ID:") + " " + statusID + "\t" +
|
||||
|
|
Loading…
Reference in a new issue