From cfb24f7e37e7afc06f278ffff64a777770eabb65 Mon Sep 17 00:00:00 2001 From: Adam Shamblin Date: Fri, 30 Dec 2022 10:31:00 -0700 Subject: [PATCH] add status types, add account status command --- cmd/account.go | 25 +++++++++++ pkg/mastodon/account.go | 32 +++++++++++++- pkg/mastodon/status.go | 93 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 pkg/mastodon/status.go diff --git a/cmd/account.go b/cmd/account.go index 0555c31..4e9021a 100644 --- a/cmd/account.go +++ b/cmd/account.go @@ -15,6 +15,7 @@ func init() { accountCmd.AddCommand(getFollowersCmd) accountCmd.AddCommand(getFollowingCmd) accountCmd.AddCommand(getListsCmd) + accountCmd.AddCommand(getStatusesCmd) rootCmd.AddCommand(accountCmd) } @@ -127,3 +128,27 @@ var getListsCmd = &cobra.Command{ lists.Display() }, } + +var getStatusesCmd = &cobra.Command{ + Use: "statuses", + Short: "Get account's statuses", + Long: "Fetch statuses posted by account.", + + PreRun: func(cmd *cobra.Command, args []string) { + err := account.VerifyCredentials(host, token) + if err != nil { + fmt.Println("Failed to verify credentials.") + os.Exit(1) + } + }, + + Run: func(cmd *cobra.Command, args []string) { + statuses, err := account.GetStatuses(host, token) + if err != nil { + fmt.Println("Failed to retrieve statuses.") + os.Exit(1) + } + + statuses.Display() + }, +} diff --git a/pkg/mastodon/account.go b/pkg/mastodon/account.go index 352d53d..2b21a0c 100644 --- a/pkg/mastodon/account.go +++ b/pkg/mastodon/account.go @@ -64,6 +64,7 @@ type Emoji struct { URL string `json:"url"` StaticURL string `json:"static_url"` VisibleInPicker bool `json:"visible_in_picker"` + Category string `json:"category"` } // AccountCollection is a group of Accounts @@ -286,7 +287,7 @@ func (a *Account) GetFollowing( return following, err } -// GetLists fetches all lists the user owns +// GetLists fetches all lists the account owns func (a *Account) GetLists(host string, token api.Token) (lists ListCollection, err error) { u := url.URL{ Host: host, @@ -306,3 +307,32 @@ func (a *Account) GetLists(host string, token api.Token) (lists ListCollection, return lists, err } + +// GetStatuses fetches a list of statuses by the account. +func (a *Account) GetStatuses( + host string, token api.Token) (statuses StatusCollection, err error) { + + id := url.PathEscape(a.ID) + path, err := url.JoinPath("api/v1/accounts", id, "statuses") + if err != nil { + return + } + + u := url.URL{ + Host: host, + Path: path, + } + u.Scheme = "https" + + body, err := api.Get(u, host, token) + if err != nil { + return + } + + err = json.Unmarshal(body, &statuses) + if err != nil { + return + } + + return statuses, err +} diff --git a/pkg/mastodon/status.go b/pkg/mastodon/status.go new file mode 100644 index 0000000..76f2aff --- /dev/null +++ b/pkg/mastodon/status.go @@ -0,0 +1,93 @@ +package mastodon + +import ( + "fmt" + "os" + "strings" + "text/tabwriter" +) + +// Status represents a post by an account. +type Status struct { + ID string `json:"id"` + CreatedAt string `json:"created_at"` + InReplyToID string `json:"in_reply_to_id,omitempty"` + InReplyToAccountID string `json:"in_reply_to_account_id,omitempty"` + Sensitive bool `json:"sensitive"` + SpoilerText string `json:"spoiler_text"` + Visibility string `json:"visibility"` + Language string `json:"language"` + URI string `json:"uri"` + URL string `json:"url"` + RepliesCount int `json:"replies_count"` + ReblogsCount int `json:"reblogs_count"` + FavouritesCount int `json:"favourites_count"` + Favourited bool `json:"favourited"` + Reblogged bool `json:"Reblogged"` + Muted bool `json:"muted"` + Bookmarked bool `json:"bookmarked"` + Content string `json:"content"` + Application Application `json:"application"` + Account Account `json:"account"` + Card PreviewCard `json:"card"` + Emojis []Emoji `json:"emojis,omitempty"` + MediaAttachments []MediaAttachment `json:"media_attachments"` + Mentions []Mention `json:"mentions"` + Tags []Tag `json:"tags"` +} + +// Reblog Status `json:"reblog,omitempty"` + +// StatusCollection is a group of Statuses. +type StatusCollection []Status + +// MediaAttachment represents a file or media that can be added to a status. +type MediaAttachment struct { + // TODO: Fill out struct and included substructs, with string enums for oneOfs. +} + +// Tag are hashtags used within the Status content. +type Tag struct { + Name string `json:"name"` + URL string `json:"url"` +} + +// Mention represents accounts mentioned in a Status +type Mention struct { + ID string `json:"id"` + UserName string `json:"username"` + URL string `json:"url"` + Acct string `json:"acct"` +} + +// PreviewCard represents a rich preview that is generated using OpenGraph tags +// from a URL. +type PreviewCard struct { + URL string `json:"url"` + Title string `json:"title"` + Description string `json:"description"` + Type string `json:"type"` + AuthorName string `json:"author_name"` + AuthorURL string `json:"author_url"` + ProviderName string `json:"provider_name"` + ProviderURL string `json:"provider_url"` + HTML string `json:"html"` + Width int `json:"width"` + Height int `json:"height"` + Image string `json:"image"` + EmbedURL string `json:"embed_url"` +} + +// Display a single Status +func (s *Status) Display() string { + return strings.Join([]string{s.ID, s.CreatedAt, s.URL}, "\t") +} + +// Display a collection of Statuses +func (ss StatusCollection) Display() { + w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) + for _, value := range ss { + fmt.Fprintln(w, value.Display()) + } + w.Flush() +} -- 2.39.5