Blame


1 1d5ddf5d 2024-02-20 o // apub is an implementation of the ActivityPub protocol.
2 1d5ddf5d 2024-02-20 o //
3 1d5ddf5d 2024-02-20 o // https://www.w3.org/TR/activitypub/
4 1d5ddf5d 2024-02-20 o // https://www.w3.org/TR/activitystreams-core/
5 1d5ddf5d 2024-02-20 o // https://www.w3.org/TR/activitystreams-vocabulary/
6 1d5ddf5d 2024-02-20 o package apub
7 1d5ddf5d 2024-02-20 o
8 1d5ddf5d 2024-02-20 o import (
9 1d5ddf5d 2024-02-20 o "bytes"
10 1d5ddf5d 2024-02-20 o "encoding/json"
11 1d5ddf5d 2024-02-20 o "errors"
12 1d5ddf5d 2024-02-20 o "fmt"
13 1d5ddf5d 2024-02-20 o "io"
14 1d5ddf5d 2024-02-20 o "net/mail"
15 1d5ddf5d 2024-02-20 o "strings"
16 1d5ddf5d 2024-02-20 o "time"
17 1d5ddf5d 2024-02-20 o )
18 1d5ddf5d 2024-02-20 o
19 1d5ddf5d 2024-02-20 o // @context
20 1d5ddf5d 2024-02-20 o const AtContext string = "https://www.w3.org/ns/activitystreams"
21 1d5ddf5d 2024-02-20 o
22 1d5ddf5d 2024-02-20 o const ContentType string = "application/activity+json"
23 1d5ddf5d 2024-02-20 o
24 1d5ddf5d 2024-02-20 o const AcceptMediaType string = `application/activity+json; profile="https://www.w3.org/ns/activitystreams"`
25 1d5ddf5d 2024-02-20 o
26 1d5ddf5d 2024-02-20 o const ToEveryone string = "https://www.w3.org/ns/activitystreams#Public"
27 1d5ddf5d 2024-02-20 o
28 71191436 2024-02-28 o var ErrNotExist = errors.New("no such activity")
29 71191436 2024-02-28 o
30 1d5ddf5d 2024-02-20 o type Activity struct {
31 1d5ddf5d 2024-02-20 o AtContext string `json:"@context"`
32 1d5ddf5d 2024-02-20 o ID string `json:"id"`
33 1d5ddf5d 2024-02-20 o Type string `json:"type"`
34 1d5ddf5d 2024-02-20 o Name string `json:"name,omitempty"`
35 1d5ddf5d 2024-02-20 o Actor string `json:"actor,omitempty"`
36 1d5ddf5d 2024-02-20 o Username string `json:"preferredUsername,omitempty"`
37 71191436 2024-02-28 o Summary string `json:"summary"`
38 1d5ddf5d 2024-02-20 o Inbox string `json:"inbox,omitempty"`
39 1d5ddf5d 2024-02-20 o Outbox string `json:"outbox,omitempty"`
40 1d5ddf5d 2024-02-20 o To []string `json:"to,omitempty"`
41 1d5ddf5d 2024-02-20 o CC []string `json:"cc,omitempty"`
42 1d5ddf5d 2024-02-20 o InReplyTo string `json:"inReplyTo,omitempty"`
43 1d5ddf5d 2024-02-20 o Published *time.Time `json:"published,omitempty"`
44 1d5ddf5d 2024-02-20 o AttributedTo string `json:"attributedTo,omitempty"`
45 1d5ddf5d 2024-02-20 o Content string `json:"content,omitempty"`
46 1d5ddf5d 2024-02-20 o MediaType string `json:"mediaType,omitempty"`
47 1d5ddf5d 2024-02-20 o Source struct {
48 1d5ddf5d 2024-02-20 o Content string `json:"content,omitempty"`
49 1d5ddf5d 2024-02-20 o MediaType string `json:"mediaType,omitempty"`
50 1d5ddf5d 2024-02-20 o } `json:"source,omitempty"`
51 1d5ddf5d 2024-02-20 o Audience string `json:"audience,omitempty"`
52 1d5ddf5d 2024-02-20 o Object json.RawMessage `json:"object,omitempty"`
53 1d5ddf5d 2024-02-20 o }
54 1d5ddf5d 2024-02-20 o
55 1d5ddf5d 2024-02-20 o func (act *Activity) UnmarshalJSON(b []byte) error {
56 1d5ddf5d 2024-02-20 o type Alias Activity
57 1d5ddf5d 2024-02-20 o aux := &struct {
58 1d5ddf5d 2024-02-20 o AtContext interface{} `json:"@context"`
59 1d5ddf5d 2024-02-20 o Object interface{}
60 1d5ddf5d 2024-02-20 o *Alias
61 1d5ddf5d 2024-02-20 o }{
62 1d5ddf5d 2024-02-20 o Alias: (*Alias)(act),
63 1d5ddf5d 2024-02-20 o }
64 1d5ddf5d 2024-02-20 o if err := json.Unmarshal(b, &aux); err != nil {
65 1d5ddf5d 2024-02-20 o return err
66 1d5ddf5d 2024-02-20 o }
67 1d5ddf5d 2024-02-20 o switch v := aux.AtContext.(type) {
68 1d5ddf5d 2024-02-20 o case string:
69 1d5ddf5d 2024-02-20 o act.AtContext = v
70 1d5ddf5d 2024-02-20 o case []interface{}:
71 1d5ddf5d 2024-02-20 o if vv, ok := v[0].(string); ok {
72 1d5ddf5d 2024-02-20 o act.AtContext = vv
73 1d5ddf5d 2024-02-20 o }
74 1d5ddf5d 2024-02-20 o }
75 1d5ddf5d 2024-02-20 o return nil
76 1d5ddf5d 2024-02-20 o }
77 1d5ddf5d 2024-02-20 o
78 1d5ddf5d 2024-02-20 o func (act *Activity) Unwrap(client *Client) (*Activity, error) {
79 1d5ddf5d 2024-02-20 o if act.Object == nil {
80 1d5ddf5d 2024-02-20 o return nil, errors.New("no wrapped activity")
81 1d5ddf5d 2024-02-20 o }
82 1d5ddf5d 2024-02-20 o
83 1d5ddf5d 2024-02-20 o var buf io.Reader
84 1d5ddf5d 2024-02-20 o buf = bytes.NewReader(act.Object)
85 1d5ddf5d 2024-02-20 o if strings.HasPrefix(string(act.Object), "https") {
86 1d5ddf5d 2024-02-20 o if client == nil {
87 1d5ddf5d 2024-02-20 o return Lookup(string(act.Object))
88 1d5ddf5d 2024-02-20 o }
89 1d5ddf5d 2024-02-20 o return client.Lookup(string(act.Object))
90 1d5ddf5d 2024-02-20 o }
91 1d5ddf5d 2024-02-20 o return Decode(buf)
92 1d5ddf5d 2024-02-20 o }
93 1d5ddf5d 2024-02-20 o
94 1d5ddf5d 2024-02-20 o func Decode(r io.Reader) (*Activity, error) {
95 1d5ddf5d 2024-02-20 o var a Activity
96 1d5ddf5d 2024-02-20 o if err := json.NewDecoder(r).Decode(&a); err != nil {
97 1d5ddf5d 2024-02-20 o return nil, fmt.Errorf("decode activity: %w", err)
98 1d5ddf5d 2024-02-20 o }
99 1d5ddf5d 2024-02-20 o return &a, nil
100 1d5ddf5d 2024-02-20 o }
101 1d5ddf5d 2024-02-20 o
102 71191436 2024-02-28 o func DecodeActor(r io.Reader) (*Actor, error) {
103 71191436 2024-02-28 o a, err := Decode(r)
104 71191436 2024-02-28 o if err != nil {
105 71191436 2024-02-28 o return nil, err
106 71191436 2024-02-28 o }
107 71191436 2024-02-28 o return activityToActor(a), nil
108 71191436 2024-02-28 o }
109 71191436 2024-02-28 o
110 1d5ddf5d 2024-02-20 o type Actor struct {
111 71191436 2024-02-28 o AtContext string `json:"@context"`
112 71191436 2024-02-28 o ID string `json:"id"`
113 71191436 2024-02-28 o Type string `json:"type"`
114 71191436 2024-02-28 o Name string `json:"name"`
115 71191436 2024-02-28 o Username string `json:"preferredUsername"`
116 71191436 2024-02-28 o Summary string `json:"summary"`
117 71191436 2024-02-28 o Inbox string `json:"inbox"`
118 71191436 2024-02-28 o Outbox string `json:"outbox"`
119 71191436 2024-02-28 o Published *time.Time `json:"published,omitempty"`
120 71191436 2024-02-28 o PublicKey PublicKey `json:"publicKey"`
121 1d5ddf5d 2024-02-20 o }
122 1d5ddf5d 2024-02-20 o
123 1d5ddf5d 2024-02-20 o type PublicKey struct {
124 1d5ddf5d 2024-02-20 o ID string `json:"id"`
125 1d5ddf5d 2024-02-20 o Owner string `json:"owner"`
126 1d5ddf5d 2024-02-20 o PublicKeyPEM string `json:"publicKeyPem"`
127 1d5ddf5d 2024-02-20 o }
128 1d5ddf5d 2024-02-20 o
129 1d5ddf5d 2024-02-20 o func (a *Actor) Address() *mail.Address {
130 71191436 2024-02-28 o if a.Username == "" && a.Name == "" {
131 71191436 2024-02-28 o return &mail.Address{"", a.ID}
132 71191436 2024-02-28 o }
133 1d5ddf5d 2024-02-20 o trimmed := strings.TrimPrefix(a.ID, "https://")
134 1d5ddf5d 2024-02-20 o host, _, _ := strings.Cut(trimmed, "/")
135 1d5ddf5d 2024-02-20 o addr := fmt.Sprintf("%s@%s", a.Username, host)
136 1d5ddf5d 2024-02-20 o return &mail.Address{a.Name, addr}
137 1d5ddf5d 2024-02-20 o }