Federated via graft
1.1 kB
37 lines
1package sync
2
3import (
4 "fmt"
5
6 "graft/internal/atproto"
7)
8
9// BlueskyPoster posts short notes to one Bluesky account on behalf of a
10// repo pair. Nil-safe: a nil *BlueskyPoster's Post is a silent no-op, so
11// every call site can post unconditionally instead of nil-checking —
12// matching the "absent config = feature off, never an error" rule for
13// this integration (see config.RepoPair.Bluesky).
14type BlueskyPoster struct {
15 Handle string
16 AppPassword string
17 PDSHost string
18}
19
20// Post logs in fresh and publishes text, returning the new post's AT-URI
21// (used to recognize a later reply to it). A new session per post is
22// wasteful but simple and avoids session-expiry bookkeeping — acceptable
23// given how infrequently a single pair mirrors new content.
24func (b *BlueskyPoster) Post(text string) (uri string, err error) {
25 if b == nil {
26 return "", nil
27 }
28 c := atproto.New(b.PDSHost)
29 if err := c.Login(b.Handle, b.AppPassword); err != nil {
30 return "", fmt.Errorf("bluesky login: %w", err)
31 }
32 uri, err = c.Post(text)
33 if err != nil {
34 return "", fmt.Errorf("bluesky post: %w", err)
35 }
36 return uri, nil
37}