Skip to content

Commit

Permalink
sorry kim
Browse files Browse the repository at this point in the history
  • Loading branch information
tsmethurst committed Nov 9, 2023
1 parent 42a19cf commit c5f9d14
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 6 deletions.
2 changes: 0 additions & 2 deletions docs/api/swagger.yaml
Expand Up @@ -2072,8 +2072,6 @@ definitions:
description: |-
Duration the poll should be open, in seconds.
If provided, media_ids cannot be used, and poll[options] must be provided.
format: int64
type: integer
x-go-name: ExpiresIn
hide_totals:
description: Hide vote counts until the poll ends.
Expand Down
49 changes: 48 additions & 1 deletion internal/api/client/polls/polls_vote.go
Expand Up @@ -18,7 +18,9 @@
package polls

import (
"fmt"
"net/http"
"strconv"

"github.com/gin-gonic/gin"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
Expand Down Expand Up @@ -105,11 +107,17 @@ func (m *Module) PollVotePOSTHandler(c *gin.Context) {
return
}

choices, errWithCode := parseChoices(form.Choices)
if errWithCode != nil {
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
return
}

poll, errWithCode := m.processor.Polls().PollVote(
c.Request.Context(),
authed.Account,
pollID,
form.Choices,
choices,
)
if errWithCode != nil {
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
Expand All @@ -118,3 +126,42 @@ func (m *Module) PollVotePOSTHandler(c *gin.Context) {

c.JSON(http.StatusOK, poll)
}

// parseChoices tries to convert an interface slice into a slice of ints.
// This is rather horrible, but regrettably necessary to get some no-longer
// maintained clients working properly with GoToSocial (Pinafore and derivatives).
func parseChoices(choicesI []interface{}) ([]int, gtserror.WithCode) {
var (
choices = make([]int, 0, len(choicesI))
err error
)

choicesL:
for _, choiceI := range choicesI {
switch c := choiceI.(type) {
case int:
choices = append(choices, c)

case string:
var i int

i, err = strconv.Atoi(c)
if err != nil {
err = fmt.Errorf("could not parse choice string '%s' as valid integer", c)
break choicesL
}

choices = append(choices, i)

default:
err = fmt.Errorf("could not parse choice type %T as valid integer", c)
break choicesL
}
}

if err != nil {
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}

return choices, nil
}
4 changes: 2 additions & 2 deletions internal/api/model/poll.go
Expand Up @@ -80,7 +80,7 @@ type PollRequest struct {

// Duration the poll should be open, in seconds.
// If provided, media_ids cannot be used, and poll[options] must be provided.
ExpiresIn int `form:"expires_in" json:"expires_in" xml:"expires_in"`
ExpiresIn interface{} `form:"expires_in" json:"expires_in" xml:"expires_in"`

// Allow multiple choices on this poll.
Multiple bool `form:"multiple" json:"multiple" xml:"multiple"`
Expand All @@ -95,5 +95,5 @@ type PollRequest struct {
type PollVoteRequest struct {
// Choices contains poll vote choice indices. Note that form
// uses a different key than the JSON, i.e. the '[]' suffix.
Choices []int `form:"choices[]" json:"choices" xml:"choices"`
Choices []interface{} `form:"choices[]" json:"choices" xml:"choices"`
}
32 changes: 31 additions & 1 deletion internal/processing/status/create.go
Expand Up @@ -21,6 +21,7 @@ import (
"context"
"errors"
"fmt"
"strconv"
"time"

"github.com/superseriousbusiness/gotosocial/internal/ap"
Expand Down Expand Up @@ -70,8 +71,37 @@ func (p *Processor) Create(ctx context.Context, requestingAccount *gtsmodel.Acco
// Update the status AS type to "Question".
status.ActivityStreamsType = ap.ActivityQuestion

// Check if "expires_in" seconds
// provided as integer or string.
var (
secs time.Duration
err error
)

switch e := form.Poll.ExpiresIn.(type) {
case int:
secs = time.Duration(e)

case string:
var i int

i, err = strconv.Atoi(e)
if err != nil {
err = fmt.Errorf("could not parse expires_in string '%s' as valid integer", e)
break
}

secs = time.Duration(i)

default:
err = fmt.Errorf("could not parse expires_in type %T as valid duration", e)
}

if err != nil {
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}

// Create new poll for status from form.
secs := time.Duration(form.Poll.ExpiresIn)
status.Poll = &gtsmodel.Poll{
ID: id.NewULID(),
Multiple: &form.Poll.Multiple,
Expand Down

0 comments on commit c5f9d14

Please sign in to comment.