summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/db/bundb/poll.go5
-rw-r--r--internal/processing/status/create.go74
-rw-r--r--internal/typeutils/internaltoas.go4
3 files changed, 53 insertions, 30 deletions
diff --git a/internal/db/bundb/poll.go b/internal/db/bundb/poll.go
index b9384774b..e8c3e7e54 100644
--- a/internal/db/bundb/poll.go
+++ b/internal/db/bundb/poll.go
@@ -88,12 +88,15 @@ func (p *pollDB) getPoll(ctx context.Context, lookup string, dbQuery func(*gtsmo
func (p *pollDB) GetOpenPolls(ctx context.Context) ([]*gtsmodel.Poll, error) {
var pollIDs []string
- // Select all polls with unset `closed_at` time.
+ // Select all polls with:
+ // - UNSET `closed_at`
+ // - SET `expires_at`
if err := p.db.NewSelect().
Table("polls").
Column("polls.id").
Join("JOIN ? ON ? = ?", bun.Ident("statuses"), bun.Ident("polls.id"), bun.Ident("statuses.poll_id")).
Where("? = true", bun.Ident("statuses.local")).
+ Where("? IS NOT NULL", bun.Ident("polls.expires_at")).
Where("? IS NULL", bun.Ident("polls.closed_at")).
Scan(ctx, &pollIDs); err != nil {
return nil, err
diff --git a/internal/processing/status/create.go b/internal/processing/status/create.go
index ef8f8aa56..340cf9ff3 100644
--- a/internal/processing/status/create.go
+++ b/internal/processing/status/create.go
@@ -85,25 +85,8 @@ func (p *Processor) Create(
PendingApproval: util.Ptr(false),
}
- if form.Poll != nil {
- // Update the status AS type to "Question".
- status.ActivityStreamsType = ap.ActivityQuestion
-
- // Create new poll for status from form.
- secs := time.Duration(form.Poll.ExpiresIn)
- status.Poll = &gtsmodel.Poll{
- ID: id.NewULID(),
- Multiple: &form.Poll.Multiple,
- HideCounts: &form.Poll.HideTotals,
- Options: form.Poll.Options,
- StatusID: statusID,
- Status: status,
- ExpiresAt: now.Add(secs * time.Second),
- }
-
- // Set poll ID on the status.
- status.PollID = status.Poll.ID
- }
+ // Process any attached poll.
+ p.processPoll(status, form.Poll)
// Check + attach in-reply-to status.
if errWithCode := p.processInReplyTo(ctx,
@@ -153,6 +136,14 @@ func (p *Processor) Create(
return nil, gtserror.NewErrorInternalError(err)
}
+ if status.Poll != nil && !status.Poll.ExpiresAt.IsZero() {
+ // Now that the status is inserted, and side effects queued,
+ // attempt to schedule an expiry handler for the status poll.
+ if err := p.polls.ScheduleExpiry(ctx, status.Poll); err != nil {
+ log.Errorf(ctx, "error scheduling poll expiry: %v", err)
+ }
+ }
+
// send it back to the client API worker for async side-effects.
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
APObjectType: ap.ObjectNote,
@@ -161,14 +152,6 @@ func (p *Processor) Create(
Origin: requester,
})
- if status.Poll != nil {
- // Now that the status is inserted, and side effects queued,
- // attempt to schedule an expiry handler for the status poll.
- if err := p.polls.ScheduleExpiry(ctx, status.Poll); err != nil {
- log.Errorf(ctx, "error scheduling poll expiry: %v", err)
- }
- }
-
// If the new status replies to a status that
// replies to us, use our reply as an implicit
// accept of any pending interaction.
@@ -189,6 +172,43 @@ func (p *Processor) Create(
return p.c.GetAPIStatus(ctx, requester, status)
}
+func (p *Processor) processPoll(status *gtsmodel.Status, poll *apimodel.PollRequest) {
+ if poll == nil {
+ // No poll set.
+ // Nothing to do.
+ return
+ }
+
+ var expiresAt time.Time
+
+ // Now will have been set
+ // as the status creation.
+ now := status.CreatedAt
+
+ // Update the status AS type to "Question".
+ status.ActivityStreamsType = ap.ActivityQuestion
+
+ // Set an expiry time if one given.
+ if in := poll.ExpiresIn; in > 0 {
+ expiresIn := time.Duration(in)
+ expiresAt = now.Add(expiresIn * time.Second)
+ }
+
+ // Create new poll for status.
+ status.Poll = &gtsmodel.Poll{
+ ID: id.NewULID(),
+ Multiple: &poll.Multiple,
+ HideCounts: &poll.HideTotals,
+ Options: poll.Options,
+ StatusID: status.ID,
+ Status: status,
+ ExpiresAt: expiresAt,
+ }
+
+ // Set poll ID on the status.
+ status.PollID = status.Poll.ID
+}
+
func (p *Processor) processInReplyTo(ctx context.Context, requester *gtsmodel.Account, status *gtsmodel.Status, inReplyToID string) gtserror.WithCode {
if inReplyToID == "" {
// Not a reply.
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
index a81e5d2c0..d46ce64e2 100644
--- a/internal/typeutils/internaltoas.go
+++ b/internal/typeutils/internaltoas.go
@@ -444,7 +444,7 @@ func (c *Converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (ap.Stat
poll := streams.NewActivityStreamsQuestion()
// Add required status poll data to AS Question.
- if err := c.addPollToAS(ctx, s.Poll, poll); err != nil {
+ if err := c.addPollToAS(s.Poll, poll); err != nil {
return nil, gtserror.Newf("error converting poll: %w", err)
}
@@ -708,7 +708,7 @@ func (c *Converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (ap.Stat
return status, nil
}
-func (c *Converter) addPollToAS(ctx context.Context, poll *gtsmodel.Poll, dst ap.Pollable) error {
+func (c *Converter) addPollToAS(poll *gtsmodel.Poll, dst ap.Pollable) error {
var optionsProp interface {
// the minimum interface for appending AS Notes
// to an AS type options property of some kind.