Skip to content
quarry Artifact [452a1940b0]
Login

Artifact [452a1940b0]

Artifact 452a1940b034114dd29de364674b4ee8649574db0dd0a67201ab440d86b64695:


package notify

import (
	"context"
	"encoding/json"
	"fmt"
	"net/url"
)

// PushResult is how one triggered push went, as notify recorded it on
// the push message: Status is notify's word (sent, error, skipped) and
// Error its text, which names each device that refused and why. Found
// is false until the push step has run.
type PushResult struct {
	Found  bool
	Status string
	Error  string
}

// PushOutcome reads the push message notify wrote for one trigger,
// found by its transaction id: the notification first, then its
// messages. notify's domain types carry no json tags, so the keys are
// the Go field names (ID, Channel, Status, ErrorText).
func (c *Client) PushOutcome(ctx context.Context, subscriber, txn string) (PushResult, error) {
	if c == nil || c.base == "" || txn == "" {
		return PushResult{}, nil
	}
	q := url.Values{"transactionId": {txn}, "limit": {"1"}}
	if subscriber != "" {
		q.Set("subscriberId", subscriber)
	}
	status, body, err := c.do(ctx, "GET", "/v1/notifications?"+q.Encode(), nil)
	if err != nil {
		return PushResult{}, fmt.Errorf("notify: push outcome: %w", err)
	}
	if status >= 300 {
		return PushResult{}, fmt.Errorf("notify: push outcome: status %d", status)
	}
	var list struct {
		Items []struct {
			ID string `json:"ID"`
		} `json:"items"`
	}
	if err := json.Unmarshal(body, &list); err != nil {
		return PushResult{}, fmt.Errorf("notify: push outcome: %w", err)
	}
	if len(list.Items) == 0 || list.Items[0].ID == "" {
		return PushResult{}, nil
	}
	status, body, err = c.do(ctx, "GET", "/v1/notifications/"+url.PathEscape(list.Items[0].ID)+"/messages", nil)
	if err != nil {
		return PushResult{}, fmt.Errorf("notify: push outcome: %w", err)
	}
	if status >= 300 {
		return PushResult{}, fmt.Errorf("notify: push outcome: status %d", status)
	}
	var msgs []struct {
		Channel   string `json:"Channel"`
		Status    string `json:"Status"`
		ErrorText string `json:"ErrorText"`
	}
	if err := json.Unmarshal(body, &msgs); err != nil {
		return PushResult{}, fmt.Errorf("notify: push outcome: %w", err)
	}
	for _, m := range msgs {
		if m.Channel == "push" {
			return PushResult{Found: true, Status: m.Status, Error: m.ErrorText}, nil
		}
	}
	return PushResult{}, nil
}