Compare commits
No commits in common. "2f530bca5a35c58c089ff84df4b4765afed349e5" and "b77bbaa6e0fc8ad43ffec58dbc2be4663ce0f8ff" have entirely different histories.
2f530bca5a
...
b77bbaa6e0
11 changed files with 197 additions and 179 deletions
|
@ -536,7 +536,16 @@ See [Create a status](#create-a-status).
|
||||||
|
|
||||||
### View a poll
|
### View a poll
|
||||||
|
|
||||||
You can view a poll from a status or timeline.
|
Prints the poll information to the screen.
|
||||||
|
|
||||||
|
```
|
||||||
|
enbas show --type poll --poll-id 01J0CEEZBZ6E6AYQSJPHCQYBDA
|
||||||
|
```
|
||||||
|
|
||||||
|
| flag | type | required | description | default |
|
||||||
|
|------|------|----------|-------------|---------|
|
||||||
|
| `type` | string | true | The resource you want to view.<br>Here this should be `poll`. | |
|
||||||
|
| `poll-id` | string | true | The ID of the poll that you want to view. | |
|
||||||
|
|
||||||
### Vote in a poll
|
### Vote in a poll
|
||||||
|
|
||||||
|
|
|
@ -5,34 +5,36 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
pollPath string = "/api/v1/polls"
|
pollPath string = "/api/v1/polls"
|
||||||
)
|
)
|
||||||
|
|
||||||
// func (g *Client) GetPoll(pollID string) (model.Poll, error) {
|
func (g *Client) GetPoll(pollID string) (model.Poll, error) {
|
||||||
// url := g.Authentication.Instance + pollPath + "/" + pollID
|
url := g.Authentication.Instance + pollPath + "/" + pollID
|
||||||
//
|
|
||||||
// var poll model.Poll
|
var poll model.Poll
|
||||||
//
|
|
||||||
// params := requestParameters{
|
params := requestParameters{
|
||||||
// httpMethod: http.MethodGet,
|
httpMethod: http.MethodGet,
|
||||||
// url: url,
|
url: url,
|
||||||
// requestBody: nil,
|
requestBody: nil,
|
||||||
// contentType: "",
|
contentType: "",
|
||||||
// output: &poll,
|
output: &poll,
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// if err := g.sendRequest(params); err != nil {
|
if err := g.sendRequest(params); err != nil {
|
||||||
// return model.Poll{}, fmt.Errorf(
|
return model.Poll{}, fmt.Errorf(
|
||||||
// "received an error after sending the request to get the poll: %w",
|
"received an error after sending the request to get the poll: %w",
|
||||||
// err,
|
err,
|
||||||
// )
|
)
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// return poll, nil
|
return poll, nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
func (g *Client) VoteInPoll(pollID string, choices []int) error {
|
func (g *Client) VoteInPoll(pollID string, choices []int) error {
|
||||||
form := struct {
|
form := struct {
|
||||||
|
|
|
@ -17,6 +17,7 @@ func (a *AddExecutor) Execute() error {
|
||||||
resourceAccount: a.addToAccount,
|
resourceAccount: a.addToAccount,
|
||||||
resourceBookmarks: a.addToBookmarks,
|
resourceBookmarks: a.addToBookmarks,
|
||||||
resourceStatus: a.addToStatus,
|
resourceStatus: a.addToStatus,
|
||||||
|
resourcePoll: a.addToPoll,
|
||||||
}
|
}
|
||||||
|
|
||||||
doFunc, ok := funcMap[a.toResourceType]
|
doFunc, ok := funcMap[a.toResourceType]
|
||||||
|
@ -163,7 +164,6 @@ func (a *AddExecutor) addToStatus(gtsClient *client.Client) error {
|
||||||
resourceStar: a.addStarToStatus,
|
resourceStar: a.addStarToStatus,
|
||||||
resourceLike: a.addStarToStatus,
|
resourceLike: a.addStarToStatus,
|
||||||
resourceBoost: a.addBoostToStatus,
|
resourceBoost: a.addBoostToStatus,
|
||||||
resourceVote: a.addVoteToStatus,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doFunc, ok := funcMap[a.resourceType]
|
doFunc, ok := funcMap[a.resourceType]
|
||||||
|
@ -197,40 +197,45 @@ func (a *AddExecutor) addBoostToStatus(gtsClient *client.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AddExecutor) addVoteToStatus(gtsClient *client.Client) error {
|
func (a *AddExecutor) addToPoll(gtsClient *client.Client) error {
|
||||||
|
if a.pollID == "" {
|
||||||
|
return FlagNotSetError{flagText: flagPollID}
|
||||||
|
}
|
||||||
|
|
||||||
|
funcMap := map[string]func(*client.Client) error{
|
||||||
|
resourceVote: a.addVoteToPoll,
|
||||||
|
}
|
||||||
|
|
||||||
|
doFunc, ok := funcMap[a.resourceType]
|
||||||
|
if !ok {
|
||||||
|
return UnsupportedAddOperationError{
|
||||||
|
ResourceType: a.resourceType,
|
||||||
|
AddToResourceType: a.toResourceType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return doFunc(gtsClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AddExecutor) addVoteToPoll(gtsClient *client.Client) error {
|
||||||
if a.votes.Empty() {
|
if a.votes.Empty() {
|
||||||
return errors.New("please use --" + flagVote + " to make a choice in this poll")
|
return errors.New("please use --" + flagVote + " to make a choice in this poll")
|
||||||
}
|
}
|
||||||
|
|
||||||
status, err := gtsClient.GetStatus(a.statusID)
|
poll, err := gtsClient.GetPoll(a.pollID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get the status: %w", err)
|
return fmt.Errorf("unable to retrieve the poll: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.Poll == nil {
|
if poll.Expired {
|
||||||
return errors.New("this status does not have a poll")
|
|
||||||
}
|
|
||||||
|
|
||||||
if status.Poll.Expired {
|
|
||||||
return PollClosedError{}
|
return PollClosedError{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !status.Poll.Multiple && !a.votes.ExpectedLength(1) {
|
if !poll.Multiple && !a.votes.ExpectedLength(1) {
|
||||||
return MultipleChoiceError{}
|
return MultipleChoiceError{}
|
||||||
}
|
}
|
||||||
|
|
||||||
myAccountID, err := getAccountID(gtsClient, true, nil, a.config.CredentialsFile)
|
if err := gtsClient.VoteInPoll(a.pollID, []int(a.votes)); err != nil {
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to get your account ID: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if status.Account.ID == myAccountID {
|
|
||||||
return errors.New("you cannot vote in your own poll")
|
|
||||||
}
|
|
||||||
|
|
||||||
pollID := status.Poll.ID
|
|
||||||
|
|
||||||
if err := gtsClient.VoteInPoll(pollID, []int(a.votes)); err != nil {
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,8 @@ func (c *CreateExecutor) createStatus(gtsClient *client.Client) error {
|
||||||
return fmt.Errorf("unable to create the status: %w", err)
|
return fmt.Errorf("unable to create the status: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.printer.PrintSuccess("Successfully created the status with ID: " + status.ID)
|
c.printer.PrintSuccess("Successfully created the following status:")
|
||||||
|
c.printer.PrintStatus(status)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ type AddExecutor struct {
|
||||||
accountNames internalFlag.StringSliceValue
|
accountNames internalFlag.StringSliceValue
|
||||||
content string
|
content string
|
||||||
listID string
|
listID string
|
||||||
|
pollID string
|
||||||
statusID string
|
statusID string
|
||||||
toResourceType string
|
toResourceType string
|
||||||
resourceType string
|
resourceType string
|
||||||
|
@ -79,6 +80,7 @@ func NewAddExecutor(
|
||||||
exe.Var(&exe.accountNames, "account-name", "The name of the account")
|
exe.Var(&exe.accountNames, "account-name", "The name of the account")
|
||||||
exe.StringVar(&exe.content, "content", "", "The content of the created resource")
|
exe.StringVar(&exe.content, "content", "", "The content of the created resource")
|
||||||
exe.StringVar(&exe.listID, "list-id", "", "The ID of the list in question")
|
exe.StringVar(&exe.listID, "list-id", "", "The ID of the list in question")
|
||||||
|
exe.StringVar(&exe.pollID, "poll-id", "", "The ID of the poll")
|
||||||
exe.StringVar(&exe.statusID, "status-id", "", "The ID of the status")
|
exe.StringVar(&exe.statusID, "status-id", "", "The ID of the status")
|
||||||
exe.StringVar(&exe.toResourceType, "to", "", "The resource type to action the target resource to (e.g. status)")
|
exe.StringVar(&exe.toResourceType, "to", "", "The resource type to action the target resource to (e.g. status)")
|
||||||
exe.StringVar(&exe.resourceType, "type", "", "The type of resource you want to action on (e.g. account, status)")
|
exe.StringVar(&exe.resourceType, "type", "", "The type of resource you want to action on (e.g. account, status)")
|
||||||
|
@ -432,6 +434,7 @@ type ShowExecutor struct {
|
||||||
onlyMedia bool
|
onlyMedia bool
|
||||||
onlyPinned bool
|
onlyPinned bool
|
||||||
onlyPublic bool
|
onlyPublic bool
|
||||||
|
pollID string
|
||||||
showUserPreferences bool
|
showUserPreferences bool
|
||||||
showStatuses bool
|
showStatuses bool
|
||||||
skipAccountRelationship bool
|
skipAccountRelationship bool
|
||||||
|
@ -469,6 +472,7 @@ func NewShowExecutor(
|
||||||
exe.BoolVar(&exe.onlyMedia, "only-media", false, "Set to true to show only the statuses with media attachments")
|
exe.BoolVar(&exe.onlyMedia, "only-media", false, "Set to true to show only the statuses with media attachments")
|
||||||
exe.BoolVar(&exe.onlyPinned, "only-pinned", false, "Set to true to show only the account's pinned statuses")
|
exe.BoolVar(&exe.onlyPinned, "only-pinned", false, "Set to true to show only the account's pinned statuses")
|
||||||
exe.BoolVar(&exe.onlyPublic, "only-public", false, "Set to true to show only the account's public posts")
|
exe.BoolVar(&exe.onlyPublic, "only-public", false, "Set to true to show only the account's public posts")
|
||||||
|
exe.StringVar(&exe.pollID, "poll-id", "", "The ID of the poll")
|
||||||
exe.BoolVar(&exe.showUserPreferences, "show-preferences", false, "Set to true to view your posting preferences when viewing your account information")
|
exe.BoolVar(&exe.showUserPreferences, "show-preferences", false, "Set to true to view your posting preferences when viewing your account information")
|
||||||
exe.BoolVar(&exe.showStatuses, "show-statuses", false, "Set to true to view the statuses created from the account you are viewing")
|
exe.BoolVar(&exe.showStatuses, "show-statuses", false, "Set to true to view the statuses created from the account you are viewing")
|
||||||
exe.BoolVar(&exe.skipAccountRelationship, "skip-relationship", false, "Set to true to skip showing your relationship to the account that you are viewing")
|
exe.BoolVar(&exe.skipAccountRelationship, "skip-relationship", false, "Set to true to skip showing your relationship to the account that you are viewing")
|
||||||
|
|
|
@ -28,6 +28,7 @@ func (s *ShowExecutor) Execute() error {
|
||||||
resourceLiked: s.showLiked,
|
resourceLiked: s.showLiked,
|
||||||
resourceStarred: s.showLiked,
|
resourceStarred: s.showLiked,
|
||||||
resourceFollowRequest: s.showFollowRequests,
|
resourceFollowRequest: s.showFollowRequests,
|
||||||
|
resourcePoll: s.showPoll,
|
||||||
resourceMutedAccounts: s.showMutedAccounts,
|
resourceMutedAccounts: s.showMutedAccounts,
|
||||||
resourceMedia: s.showMedia,
|
resourceMedia: s.showMedia,
|
||||||
resourceMediaAttachment: s.showMediaAttachment,
|
resourceMediaAttachment: s.showMediaAttachment,
|
||||||
|
@ -75,7 +76,6 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
||||||
relationship *model.AccountRelationship
|
relationship *model.AccountRelationship
|
||||||
preferences *model.Preferences
|
preferences *model.Preferences
|
||||||
statuses *model.StatusList
|
statuses *model.StatusList
|
||||||
myAccountID string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if !s.myAccount && !s.skipAccountRelationship {
|
if !s.myAccount && !s.skipAccountRelationship {
|
||||||
|
@ -85,13 +85,10 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.myAccount {
|
if s.myAccount && s.showUserPreferences {
|
||||||
myAccountID = account.ID
|
preferences, err = gtsClient.GetUserPreferences()
|
||||||
if s.showUserPreferences {
|
if err != nil {
|
||||||
preferences, err = gtsClient.GetUserPreferences()
|
return fmt.Errorf("unable to retrieve the user preferences: %w", err)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to retrieve the user preferences: %w", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +109,7 @@ func (s *ShowExecutor) showAccount(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.printer.PrintAccount(account, relationship, preferences, statuses, myAccountID)
|
s.printer.PrintAccount(account, relationship, preferences, statuses)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -135,12 +132,7 @@ func (s *ShowExecutor) showStatus(gtsClient *client.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
myAccountID, err := getAccountID(gtsClient, true, nil, s.config.CredentialsFile)
|
s.printer.PrintStatus(status)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to get your account ID: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.printer.PrintStatus(status, myAccountID)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -189,12 +181,7 @@ func (s *ShowExecutor) showTimeline(gtsClient *client.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
myAccountID, err := getAccountID(gtsClient, true, nil, s.config.CredentialsFile)
|
s.printer.PrintStatusList(timeline)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to get your account ID: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.printer.PrintStatusList(timeline, myAccountID)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -347,12 +334,7 @@ func (s *ShowExecutor) showBookmarks(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(bookmarks.Statuses) > 0 {
|
if len(bookmarks.Statuses) > 0 {
|
||||||
myAccountID, err := getAccountID(gtsClient, true, nil, s.config.CredentialsFile)
|
s.printer.PrintStatusList(bookmarks)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to get your account ID: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.printer.PrintStatusList(bookmarks, myAccountID)
|
|
||||||
} else {
|
} else {
|
||||||
s.printer.PrintInfo("You have no bookmarks.\n")
|
s.printer.PrintInfo("You have no bookmarks.\n")
|
||||||
}
|
}
|
||||||
|
@ -367,12 +349,7 @@ func (s *ShowExecutor) showLiked(gtsClient *client.Client) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(liked.Statuses) > 0 {
|
if len(liked.Statuses) > 0 {
|
||||||
myAccountID, err := getAccountID(gtsClient, true, nil, s.config.CredentialsFile)
|
s.printer.PrintStatusList(liked)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to get your account ID: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.printer.PrintStatusList(liked, myAccountID)
|
|
||||||
} else {
|
} else {
|
||||||
s.printer.PrintInfo("You have no " + s.resourceType + " statuses.\n")
|
s.printer.PrintInfo("You have no " + s.resourceType + " statuses.\n")
|
||||||
}
|
}
|
||||||
|
@ -395,6 +372,21 @@ func (s *ShowExecutor) showFollowRequests(gtsClient *client.Client) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ShowExecutor) showPoll(gtsClient *client.Client) error {
|
||||||
|
if s.pollID == "" {
|
||||||
|
return FlagNotSetError{flagText: flagPollID}
|
||||||
|
}
|
||||||
|
|
||||||
|
poll, err := gtsClient.GetPoll(s.pollID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to retrieve the poll: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.printer.PrintPoll(poll)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ShowExecutor) showMutedAccounts(gtsClient *client.Client) error {
|
func (s *ShowExecutor) showMutedAccounts(gtsClient *client.Client) error {
|
||||||
muted, err := gtsClient.GetMutedAccounts(s.limit)
|
muted, err := gtsClient.GetMutedAccounts(s.limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -12,7 +12,6 @@ func (p Printer) PrintAccount(
|
||||||
relationship *model.AccountRelationship,
|
relationship *model.AccountRelationship,
|
||||||
preferences *model.Preferences,
|
preferences *model.Preferences,
|
||||||
statuses *model.StatusList,
|
statuses *model.StatusList,
|
||||||
userAccountID string,
|
|
||||||
) {
|
) {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ func (p Printer) PrintAccount(
|
||||||
}
|
}
|
||||||
|
|
||||||
if statuses != nil {
|
if statuses != nil {
|
||||||
builder.WriteString("\n\n" + p.statusList(*statuses, userAccountID))
|
builder.WriteString("\n\n" + p.statusList(*statuses))
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.WriteString("\n\n")
|
builder.WriteString("\n\n")
|
||||||
|
|
|
@ -1,2 +1,91 @@
|
||||||
package printer
|
package printer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p Printer) PrintPoll(poll model.Poll) {
|
||||||
|
var builder strings.Builder
|
||||||
|
|
||||||
|
builder.WriteString("\n" + p.headerFormat("POLL ID:"))
|
||||||
|
builder.WriteString("\n" + poll.ID)
|
||||||
|
|
||||||
|
builder.WriteString("\n\n" + p.headerFormat("OPTIONS:"))
|
||||||
|
builder.WriteString(p.pollOptions(poll))
|
||||||
|
|
||||||
|
builder.WriteString("\n\n" + p.headerFormat("MULTIPLE CHOICES ALLOWED:"))
|
||||||
|
builder.WriteString("\n" + strconv.FormatBool(poll.Multiple))
|
||||||
|
|
||||||
|
builder.WriteString("\n\n" + p.headerFormat("YOU VOTED:"))
|
||||||
|
builder.WriteString("\n" + strconv.FormatBool(poll.Voted))
|
||||||
|
|
||||||
|
if len(poll.OwnVotes) > 0 {
|
||||||
|
builder.WriteString("\n\n" + p.headerFormat("YOUR VOTES:"))
|
||||||
|
|
||||||
|
for _, vote := range poll.OwnVotes {
|
||||||
|
builder.WriteString("\n" + "[" + strconv.Itoa(vote) + "] " + poll.Options[vote].Title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.WriteString("\n\n" + p.headerFormat("EXPIRED:"))
|
||||||
|
builder.WriteString("\n" + strconv.FormatBool(poll.Expired))
|
||||||
|
builder.WriteString("\n\n")
|
||||||
|
|
||||||
|
p.print(builder.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) pollOptions(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:") + " " + p.formatDateTime(poll.ExpiredAt))
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Printer) pollMeter(votage float64) string {
|
||||||
|
numVoteBlocks := int(math.Floor(float64(p.lineWrapCharacterLimit) * votage))
|
||||||
|
numBackgroundBlocks := p.lineWrapCharacterLimit - 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(symbolPollMeter, numVoteBlocks) + p.theme.reset
|
||||||
|
|
||||||
|
if !p.noColor {
|
||||||
|
meter += backgroundBlockColor + strings.Repeat(symbolPollMeter, numBackgroundBlocks) + p.theme.reset
|
||||||
|
}
|
||||||
|
|
||||||
|
return meter
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ const (
|
||||||
noMediaDescription = "This media attachment has no description."
|
noMediaDescription = "This media attachment has no description."
|
||||||
symbolBullet = "\u2022"
|
symbolBullet = "\u2022"
|
||||||
symbolPollMeter = "\u2501"
|
symbolPollMeter = "\u2501"
|
||||||
symbolCheckMark = "\u2714"
|
symbolSuccess = "\u2714"
|
||||||
symbolFailure = "\u2717"
|
symbolFailure = "\u2717"
|
||||||
symbolImage = "\uf03e"
|
symbolImage = "\uf03e"
|
||||||
symbolLiked = "\uf51f"
|
symbolLiked = "\uf51f"
|
||||||
|
@ -78,9 +78,9 @@ func NewPrinter(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Printer) PrintSuccess(text string) {
|
func (p Printer) PrintSuccess(text string) {
|
||||||
success := p.theme.boldgreen + symbolCheckMark + p.theme.reset
|
success := p.theme.boldgreen + symbolSuccess + p.theme.reset
|
||||||
if p.noColor {
|
if p.noColor {
|
||||||
success = symbolCheckMark
|
success = symbolSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
printToStdout(success + " " + text + "\n")
|
printToStdout(success + " " + text + "\n")
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package printer
|
package printer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p Printer) PrintStatus(status model.Status, userAccountID string) {
|
func (p Printer) PrintStatus(status model.Status) {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
|
|
||||||
// The account information
|
// The account information
|
||||||
|
@ -42,13 +41,7 @@ func (p Printer) PrintStatus(status model.Status, userAccountID string) {
|
||||||
|
|
||||||
// If a poll exists in a status, write the contents to the builder.
|
// If a poll exists in a status, write the contents to the builder.
|
||||||
if status.Poll != nil {
|
if status.Poll != nil {
|
||||||
pollOwner := false
|
builder.WriteString(p.pollOptions(*status.Poll))
|
||||||
if status.Account.ID == userAccountID {
|
|
||||||
pollOwner = true
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.WriteString("\n\n" + p.headerFormat("POLL DETAILS:"))
|
|
||||||
builder.WriteString(p.pollDetails(*status.Poll, pollOwner))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status creation time
|
// Status creation time
|
||||||
|
@ -79,18 +72,17 @@ func (p Printer) PrintStatus(status model.Status, userAccountID string) {
|
||||||
p.print(builder.String())
|
p.print(builder.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Printer) PrintStatusList(list model.StatusList, userAccountID string) {
|
func (p Printer) PrintStatusList(list model.StatusList) {
|
||||||
p.print(p.statusList(list, userAccountID))
|
p.print(p.statusList(list))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Printer) statusList(list model.StatusList, userAccountID string) string {
|
func (p Printer) statusList(list model.StatusList) string {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
|
|
||||||
builder.WriteString(p.headerFormat(list.Name) + "\n")
|
builder.WriteString(p.headerFormat(list.Name) + "\n")
|
||||||
|
|
||||||
for _, status := range list.Statuses {
|
for _, status := range list.Statuses {
|
||||||
statusID := status.ID
|
statusID := status.ID
|
||||||
statusOwnerID := status.Account.ID
|
|
||||||
createdAt := p.formatDateTime(status.CreatedAt)
|
createdAt := p.formatDateTime(status.CreatedAt)
|
||||||
boostedAt := ""
|
boostedAt := ""
|
||||||
content := status.Content
|
content := status.Content
|
||||||
|
@ -108,7 +100,6 @@ func (p Printer) statusList(list model.StatusList, userAccountID string) string
|
||||||
))
|
))
|
||||||
|
|
||||||
statusID = status.Reblog.ID
|
statusID = status.Reblog.ID
|
||||||
statusOwnerID = status.Reblog.Account.ID
|
|
||||||
createdAt = p.formatDateTime(status.Reblog.CreatedAt)
|
createdAt = p.formatDateTime(status.Reblog.CreatedAt)
|
||||||
boostedAt = p.formatDateTime(status.CreatedAt)
|
boostedAt = p.formatDateTime(status.CreatedAt)
|
||||||
content = status.Reblog.Content
|
content = status.Reblog.Content
|
||||||
|
@ -129,12 +120,7 @@ func (p Printer) statusList(list model.StatusList, userAccountID string) string
|
||||||
builder.WriteString("\n" + p.convertHTMLToText(content, true))
|
builder.WriteString("\n" + p.convertHTMLToText(content, true))
|
||||||
|
|
||||||
if poll != nil {
|
if poll != nil {
|
||||||
pollOwner := false
|
builder.WriteString(p.pollOptions(*poll))
|
||||||
if statusOwnerID == userAccountID {
|
|
||||||
pollOwner = true
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.WriteString(p.pollDetails(*poll, pollOwner))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, media := range mediaAttachments {
|
for _, media := range mediaAttachments {
|
||||||
|
@ -186,78 +172,3 @@ func (p Printer) statusList(list model.StatusList, userAccountID string) string
|
||||||
|
|
||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Printer) pollDetails(poll model.Poll, owner bool) string {
|
|
||||||
var builder strings.Builder
|
|
||||||
|
|
||||||
for ind, option := range poll.Options {
|
|
||||||
var (
|
|
||||||
votage float64
|
|
||||||
percentage int
|
|
||||||
)
|
|
||||||
|
|
||||||
// Show the poll results under any of the following conditions:
|
|
||||||
// - the user is the owner of the poll
|
|
||||||
// - the poll has expired
|
|
||||||
// - the user has voted in the poll
|
|
||||||
if owner || poll.Expired || poll.Voted {
|
|
||||||
if poll.VotesCount == 0 {
|
|
||||||
percentage = 0
|
|
||||||
} else {
|
|
||||||
votage = float64(option.VotesCount) / float64(poll.VotesCount)
|
|
||||||
percentage = int(math.Floor(100 * votage))
|
|
||||||
}
|
|
||||||
|
|
||||||
optionTitle := "\n\n" + "[" + strconv.Itoa(ind) + "] " + option.Title
|
|
||||||
|
|
||||||
for _, vote := range poll.OwnVotes {
|
|
||||||
if ind == vote {
|
|
||||||
optionTitle += " " + symbolCheckMark
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.WriteString(optionTitle)
|
|
||||||
builder.WriteString(p.pollMeter(votage))
|
|
||||||
builder.WriteString("\n" + strconv.Itoa(option.VotesCount) + " votes " + "(" + strconv.Itoa(percentage) + "%)")
|
|
||||||
} else {
|
|
||||||
builder.WriteString("\n" + "[" + strconv.Itoa(ind) + "] " + option.Title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pollStatusField := "Poll is open until: "
|
|
||||||
if poll.Expired {
|
|
||||||
pollStatusField = "Poll was closed on: "
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.WriteString("\n\n" + p.fieldFormat(pollStatusField) + p.formatDateTime(poll.ExpiredAt))
|
|
||||||
builder.WriteString("\n" + p.fieldFormat("Total votes: ") + strconv.Itoa(poll.VotesCount))
|
|
||||||
builder.WriteString("\n" + p.fieldFormat("Multiple choices allowed: ") + strconv.FormatBool(poll.Multiple))
|
|
||||||
|
|
||||||
return builder.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Printer) pollMeter(votage float64) string {
|
|
||||||
numVoteBlocks := int(math.Floor(float64(p.lineWrapCharacterLimit) * votage))
|
|
||||||
numBackgroundBlocks := p.lineWrapCharacterLimit - numVoteBlocks
|
|
||||||
|
|
||||||
voteBlockColour := p.theme.boldgreen
|
|
||||||
backgroundBlockColor := p.theme.grey
|
|
||||||
|
|
||||||
if p.noColor {
|
|
||||||
voteBlockColour = p.theme.reset
|
|
||||||
|
|
||||||
if numVoteBlocks == 0 {
|
|
||||||
numVoteBlocks = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meter := "\n" + voteBlockColour + strings.Repeat(symbolPollMeter, numVoteBlocks) + p.theme.reset
|
|
||||||
|
|
||||||
if !p.noColor {
|
|
||||||
meter += backgroundBlockColor + strings.Repeat(symbolPollMeter, numBackgroundBlocks) + p.theme.reset
|
|
||||||
}
|
|
||||||
|
|
||||||
return meter
|
|
||||||
}
|
|
||||||
|
|
|
@ -136,6 +136,10 @@
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"description": "Set to true to hide the vote count until the poll is closed"
|
"description": "Set to true to hide the vote count until the poll is closed"
|
||||||
},
|
},
|
||||||
|
"poll-id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The ID of the poll"
|
||||||
|
},
|
||||||
"poll-option": {
|
"poll-option": {
|
||||||
"type": "StringSliceValue",
|
"type": "StringSliceValue",
|
||||||
"description": "A poll option. Use this multiple times to set multiple options"
|
"description": "A poll option. Use this multiple times to set multiple options"
|
||||||
|
@ -211,6 +215,7 @@
|
||||||
{ "flag": "account-name", "fieldName": "accountNames" },
|
{ "flag": "account-name", "fieldName": "accountNames" },
|
||||||
{ "flag": "content", "default": "" },
|
{ "flag": "content", "default": "" },
|
||||||
{ "flag": "list-id", "fieldName": "listID", "default": "" },
|
{ "flag": "list-id", "fieldName": "listID", "default": "" },
|
||||||
|
{ "flag": "poll-id", "fieldName": "pollID", "default": "" },
|
||||||
{ "flag": "status-id", "fieldName": "statusID", "default": "" },
|
{ "flag": "status-id", "fieldName": "statusID", "default": "" },
|
||||||
{ "flag": "to", "fieldName": "toResourceType", "default": "" },
|
{ "flag": "to", "fieldName": "toResourceType", "default": "" },
|
||||||
{ "flag": "type", "fieldName": "resourceType", "default": "" },
|
{ "flag": "type", "fieldName": "resourceType", "default": "" },
|
||||||
|
@ -362,6 +367,7 @@
|
||||||
{ "flag": "only-media", "default": "false" },
|
{ "flag": "only-media", "default": "false" },
|
||||||
{ "flag": "only-pinned", "default": "false" },
|
{ "flag": "only-pinned", "default": "false" },
|
||||||
{ "flag": "only-public", "default": "false" },
|
{ "flag": "only-public", "default": "false" },
|
||||||
|
{ "flag": "poll-id", "fieldName": "pollID", "default": "" },
|
||||||
{ "flag": "show-preferences", "fieldName": "showUserPreferences", "default": "false" },
|
{ "flag": "show-preferences", "fieldName": "showUserPreferences", "default": "false" },
|
||||||
{ "flag": "show-statuses", "default": "false" },
|
{ "flag": "show-statuses", "default": "false" },
|
||||||
{ "flag": "skip-relationship", "fieldName": "skipAccountRelationship", "default": "false" },
|
{ "flag": "skip-relationship", "fieldName": "skipAccountRelationship", "default": "false" },
|
||||||
|
|
Loading…
Reference in a new issue