tangled
alpha
login
or
join now
moth11.net
/
88x31
0
fork
atom
tiny 88x31 lexicon for atproto
0
fork
atom
overview
issues
pulls
pipelines
add listener
moth11.net
1 month ago
871f220d
1ec1d887
+217
-32
5 changed files
expand all
collapse all
unified
split
atplistener
jetstream.go
db
lexicon.go
go.mod
go.sum
tmpl
upload.html
+170
atplistener/jetstream.go
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
package atplistener
2
+
3
+
import (
4
+
"context"
5
+
"encoding/json"
6
+
"errors"
7
+
"fmt"
8
+
"github.com/bluesky-social/jetstream/pkg/client"
9
+
"github.com/bluesky-social/jetstream/pkg/client/schedulers/sequential"
10
+
"github.com/bluesky-social/jetstream/pkg/models"
11
+
"log/slog"
12
+
"tangled.org/moth11.net/88x31/db"
13
+
"tangled.org/moth11.net/88x31/lex"
14
+
"tangled.org/moth11.net/88x31/types"
15
+
"time"
16
+
)
17
+
18
+
type Consumer struct {
19
+
cfg *client.ClientConfig
20
+
logger *slog.Logger
21
+
handler *handler
22
+
}
23
+
24
+
type handler struct {
25
+
db *db.Store
26
+
l *slog.Logger
27
+
}
28
+
29
+
func NewConsumer(jsAddr string, l *slog.Logger, db *db.Store) *Consumer {
30
+
cfg := client.DefaultClientConfig()
31
+
if jsAddr != "" {
32
+
cfg.WebsocketURL = jsAddr
33
+
}
34
+
cfg.WantedCollections = []string{
35
+
"store.88x31.button",
36
+
"store.88x31.like",
37
+
}
38
+
cfg.WantedDids = []string{}
39
+
return &Consumer{
40
+
cfg: cfg,
41
+
logger: l,
42
+
handler: &handler{db: db, l: l},
43
+
}
44
+
}
45
+
46
+
func (c *Consumer) Consume(ctx context.Context) error {
47
+
scheduler := sequential.NewScheduler("jetstream_localdev", c.logger, c.handler.HandleEvent)
48
+
defer scheduler.Shutdown()
49
+
client, err := client.NewClient(c.cfg, c.logger, scheduler)
50
+
if err != nil {
51
+
return errors.New("failed to create client: " + err.Error())
52
+
}
53
+
cursor := time.Now().Add(1 * -time.Minute).UnixMicro()
54
+
err = client.ConnectAndRead(ctx, &cursor)
55
+
if err != nil {
56
+
return errors.New("error connecting and reading: " + err.Error())
57
+
}
58
+
return nil
59
+
}
60
+
61
+
func (h *handler) HandleEvent(ctx context.Context, event *models.Event) error {
62
+
if event.Commit == nil {
63
+
return nil
64
+
}
65
+
switch event.Commit.Collection {
66
+
case "store.88x31.button":
67
+
return h.handleButton(ctx, event)
68
+
case "store.88x31.like":
69
+
return h.handleLike(ctx, event)
70
+
}
71
+
return nil
72
+
}
73
+
74
+
func (h *handler) handleButton(ctx context.Context, event *models.Event) error {
75
+
h.l.Debug("handling button")
76
+
switch event.Commit.Operation {
77
+
case "create", "update":
78
+
return h.handleButtonCreateUpdate(ctx, event)
79
+
case "delete":
80
+
return h.handleButtonDelete(ctx, event)
81
+
}
82
+
return errors.New("unsupported commit operation")
83
+
}
84
+
85
+
func (h *handler) handleButtonCreateUpdate(ctx context.Context, event *models.Event) error {
86
+
var br lex.ButtonRecord
87
+
err := json.Unmarshal(event.Commit.Record, &br)
88
+
if err != nil {
89
+
h.l.Error("error unmarshaling: " + err.Error())
90
+
return nil
91
+
}
92
+
pa, err := time.Parse(br.PostedAt, time.RFC3339)
93
+
if err != nil {
94
+
h.l.Debug("bad time: " + err.Error())
95
+
pa = time.Time{}
96
+
}
97
+
tbr := types.Button{URI: uri(event),
98
+
DID: event.Did,
99
+
BlobCID: br.Blob.Ref.String(),
100
+
BlobMIME: br.Blob.MimeType,
101
+
Alt: br.Alt,
102
+
Title: br.Title,
103
+
HREF: br.Href,
104
+
CID: event.Commit.CID,
105
+
PostedAt: pa,
106
+
}
107
+
err = h.db.StoreButton(&tbr, ctx)
108
+
if err != nil {
109
+
return err
110
+
}
111
+
return nil
112
+
}
113
+
114
+
func (h *handler) handleButtonDelete(ctx context.Context, event *models.Event) error {
115
+
116
+
err := h.db.DeleteButton(uri(event), ctx)
117
+
if err != nil {
118
+
h.l.Error(err.Error())
119
+
}
120
+
return nil
121
+
}
122
+
123
+
func uri(event *models.Event) string {
124
+
return fmt.Sprintf("at://%s/%s/%s", event.Did, event.Commit.Collection, event.Commit.RKey)
125
+
}
126
+
func (h *handler) handleLike(ctx context.Context, event *models.Event) error {
127
+
h.l.Debug("handling like")
128
+
switch event.Commit.Operation {
129
+
case "create", "update":
130
+
return h.handleLikeCreateUpdate(ctx, event)
131
+
case "delete":
132
+
return h.handleLikeDelete(ctx, event)
133
+
}
134
+
return errors.New("unsupported commit operation")
135
+
}
136
+
137
+
func (h *handler) handleLikeCreateUpdate(ctx context.Context, event *models.Event) error {
138
+
var lr lex.LikeRecord
139
+
err := json.Unmarshal(event.Commit.Record, &lr)
140
+
if err != nil {
141
+
h.l.Error("error unmarshaling: " + err.Error())
142
+
return nil
143
+
}
144
+
pa, err := time.Parse(lr.CreatedAt, time.RFC3339)
145
+
if err != nil {
146
+
h.l.Debug("bad time: " + err.Error())
147
+
pa = time.Time{}
148
+
}
149
+
tlr := types.Like{
150
+
URI: uri(event),
151
+
SubjectURI: lr.Subject.URI,
152
+
SubjectCID: lr.Subject.CID,
153
+
DID: event.Did,
154
+
CID: event.Commit.CID,
155
+
CreatedAt: pa,
156
+
}
157
+
err = h.db.StoreLike(&tlr, ctx)
158
+
if err != nil {
159
+
return err
160
+
}
161
+
return nil
162
+
}
163
+
164
+
func (h *handler) handleLikeDelete(ctx context.Context, event *models.Event) error {
165
+
err := h.db.DeleteLike(uri(event), ctx)
166
+
if err != nil {
167
+
h.l.Error(err.Error())
168
+
}
169
+
return nil
170
+
}
+1
-1
db/lexicon.go
···
260
posted_at
261
) VALUES (
262
$1, $2, $3, $4, $5, $6, $7, $8, $9
263
-
)
264
`, tbr.URI, tbr.DID, tbr.BlobCID, tbr.BlobMIME, tbr.Alt, tbr.Title, tbr.HREF, tbr.CID, tbr.PostedAt)
265
return err
266
}
···
260
posted_at
261
) VALUES (
262
$1, $2, $3, $4, $5, $6, $7, $8, $9
263
+
) ON CONFLICT (uri) DO UPDATE
264
`, tbr.URI, tbr.DID, tbr.BlobCID, tbr.BlobMIME, tbr.Alt, tbr.Title, tbr.HREF, tbr.CID, tbr.PostedAt)
265
return err
266
}
+14
-9
go.mod
···
3
go 1.25
4
5
require (
6
-
github.com/bluesky-social/indigo v0.0.0-20251127021457-6f2658724b36
0
7
github.com/gorilla/sessions v1.4.0
8
github.com/ipfs/go-cid v0.4.1
9
github.com/jackc/pgx/v5 v5.7.6
···
14
15
require (
16
github.com/beorn7/perks v1.0.1 // indirect
17
-
github.com/cespare/xxhash/v2 v2.2.0 // indirect
18
github.com/earthboundkid/versioninfo/v2 v2.24.1 // indirect
0
19
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
20
github.com/google/go-querystring v1.1.0 // indirect
21
github.com/gorilla/securecookie v1.1.2 // indirect
0
22
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
23
github.com/jackc/pgpassfile v1.0.0 // indirect
24
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
25
github.com/jackc/puddle/v2 v2.2.2 // indirect
0
26
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
27
-
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
28
github.com/minio/sha256-simd v1.0.1 // indirect
29
github.com/mr-tron/base58 v1.2.0 // indirect
30
github.com/multiformats/go-base32 v0.1.0 // indirect
···
32
github.com/multiformats/go-multibase v0.2.0 // indirect
33
github.com/multiformats/go-multihash v0.2.3 // indirect
34
github.com/multiformats/go-varint v0.0.7 // indirect
35
-
github.com/prometheus/client_golang v1.17.0 // indirect
36
-
github.com/prometheus/client_model v0.5.0 // indirect
37
-
github.com/prometheus/common v0.45.0 // indirect
38
-
github.com/prometheus/procfs v0.12.0 // indirect
39
github.com/spaolacci/murmur3 v1.1.0 // indirect
40
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
41
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
0
42
golang.org/x/crypto v0.37.0 // indirect
0
43
golang.org/x/sync v0.13.0 // indirect
44
golang.org/x/sys v0.32.0 // indirect
45
golang.org/x/text v0.24.0 // indirect
46
-
golang.org/x/time v0.3.0 // indirect
47
-
google.golang.org/protobuf v1.33.0 // indirect
48
lukechampine.com/blake3 v1.2.1 // indirect
49
)
···
3
go 1.25
4
5
require (
6
+
github.com/bluesky-social/indigo v0.0.0-20260120225912-12d69fa4d209
7
+
github.com/bluesky-social/jetstream v0.0.0-20260121001058-f4e39a4b5bbc
8
github.com/gorilla/sessions v1.4.0
9
github.com/ipfs/go-cid v0.4.1
10
github.com/jackc/pgx/v5 v5.7.6
···
15
16
require (
17
github.com/beorn7/perks v1.0.1 // indirect
18
+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
19
github.com/earthboundkid/versioninfo/v2 v2.24.1 // indirect
20
+
github.com/goccy/go-json v0.10.2 // indirect
21
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
22
github.com/google/go-querystring v1.1.0 // indirect
23
github.com/gorilla/securecookie v1.1.2 // indirect
24
+
github.com/gorilla/websocket v1.5.1 // indirect
25
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
26
github.com/jackc/pgpassfile v1.0.0 // indirect
27
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
28
github.com/jackc/puddle/v2 v2.2.2 // indirect
29
+
github.com/klauspost/compress v1.17.9 // indirect
30
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
0
31
github.com/minio/sha256-simd v1.0.1 // indirect
32
github.com/mr-tron/base58 v1.2.0 // indirect
33
github.com/multiformats/go-base32 v0.1.0 // indirect
···
35
github.com/multiformats/go-multibase v0.2.0 // indirect
36
github.com/multiformats/go-multihash v0.2.3 // indirect
37
github.com/multiformats/go-varint v0.0.7 // indirect
38
+
github.com/prometheus/client_golang v1.19.1 // indirect
39
+
github.com/prometheus/client_model v0.6.1 // indirect
40
+
github.com/prometheus/common v0.54.0 // indirect
41
+
github.com/prometheus/procfs v0.15.1 // indirect
42
github.com/spaolacci/murmur3 v1.1.0 // indirect
43
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
44
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
45
+
go.uber.org/atomic v1.11.0 // indirect
46
golang.org/x/crypto v0.37.0 // indirect
47
+
golang.org/x/net v0.24.0 // indirect
48
golang.org/x/sync v0.13.0 // indirect
49
golang.org/x/sys v0.32.0 // indirect
50
golang.org/x/text v0.24.0 // indirect
51
+
golang.org/x/time v0.5.0 // indirect
52
+
google.golang.org/protobuf v1.34.2 // indirect
53
lukechampine.com/blake3 v1.2.1 // indirect
54
)
+30
-20
go.sum
···
1
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
2
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
3
-
github.com/bluesky-social/indigo v0.0.0-20251127021457-6f2658724b36 h1:Vc+l4sltxQfBT8qC3dm87PRYInmxlGyF1dmpjaW0WkU=
4
-
github.com/bluesky-social/indigo v0.0.0-20251127021457-6f2658724b36/go.mod h1:Pm2I1+iDXn/hLbF7XCg/DsZi6uDCiOo7hZGWprSM7k0=
5
-
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
6
-
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
0
0
7
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
9
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
10
github.com/earthboundkid/versioninfo/v2 v2.24.1 h1:SJTMHaoUx3GzjjnUO1QzP3ZXK6Ee/nbWyCm58eY3oUg=
11
github.com/earthboundkid/versioninfo/v2 v2.24.1/go.mod h1:VcWEooDEuyUJnMfbdTh0uFN4cfEIg+kHMuWB2CDCLjw=
0
0
12
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
13
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
14
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
15
-
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
16
-
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
17
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
18
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
19
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
···
22
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
23
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
24
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
0
0
25
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
26
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
27
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
···
36
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
37
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
38
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
0
0
39
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
40
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
41
-
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
42
-
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
43
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
44
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
45
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
···
56
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
57
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
58
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
59
-
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
60
-
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
61
-
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
62
-
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
63
-
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
64
-
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
65
-
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
66
-
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
67
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
68
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
69
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
···
77
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8=
78
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q=
79
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I=
0
0
80
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
81
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
0
0
82
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
83
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
84
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
···
86
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
87
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
88
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
89
-
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
90
-
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
91
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
92
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
93
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
94
-
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
95
-
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
96
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
97
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
98
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
···
1
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
2
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
3
+
github.com/bluesky-social/indigo v0.0.0-20260120225912-12d69fa4d209 h1:W01PGqjCexVBzIZ4FoNe4iO8OhI9XbSE7ieWL0QnMu8=
4
+
github.com/bluesky-social/indigo v0.0.0-20260120225912-12d69fa4d209/go.mod h1:KIy0FgNQacp4uv2Z7xhNkV3qZiUSGuRky97s7Pa4v+o=
5
+
github.com/bluesky-social/jetstream v0.0.0-20260121001058-f4e39a4b5bbc h1:PhAg2bDYjOGxMTgBe4VgwrTyeEVRX+8R997TSoT15QM=
6
+
github.com/bluesky-social/jetstream v0.0.0-20260121001058-f4e39a4b5bbc/go.mod h1:vt8kVRKtvrBspt9G38wDD8+BotjIMO8u8IYoVnyE4zY=
7
+
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
8
+
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
9
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
10
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
11
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12
github.com/earthboundkid/versioninfo/v2 v2.24.1 h1:SJTMHaoUx3GzjjnUO1QzP3ZXK6Ee/nbWyCm58eY3oUg=
13
github.com/earthboundkid/versioninfo/v2 v2.24.1/go.mod h1:VcWEooDEuyUJnMfbdTh0uFN4cfEIg+kHMuWB2CDCLjw=
14
+
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
15
+
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
16
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
17
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
18
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
19
+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
20
+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
21
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
22
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
23
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
···
26
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
27
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
28
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
29
+
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
30
+
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
31
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
32
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
33
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
···
42
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
43
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
44
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
45
+
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
46
+
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
47
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
48
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
0
0
49
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
50
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
51
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
···
62
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
63
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
64
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
65
+
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
66
+
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
67
+
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
68
+
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
69
+
github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8=
70
+
github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ=
71
+
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
72
+
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
73
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
74
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
75
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
···
83
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8=
84
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q=
85
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I=
86
+
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
87
+
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
88
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
89
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
90
+
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
91
+
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
92
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
93
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
94
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
···
96
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
97
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
98
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
99
+
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
100
+
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
101
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
102
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
103
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
104
+
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
105
+
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
106
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
107
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
108
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+2
-2
tmpl/upload.html
···
1
{{define "content"}}
2
<form action="/upload" method="POST" enctype="multipart/form-data">
3
<div><input type="file" name="button" value="select file" accept="image/png, image/jpg, image/gif"/></div>
4
-
<div><input type="text" name="alt" placeholder="alt text"/></div>
5
-
<div><input type="text" name="title" placeholder="title text"/></div>
6
<div><input type="text" name="href" placeholder="link"/></div>
7
<div><input type="submit" value="upload"/></div>
8
</form>
···
1
{{define "content"}}
2
<form action="/upload" method="POST" enctype="multipart/form-data">
3
<div><input type="file" name="button" value="select file" accept="image/png, image/jpg, image/gif"/></div>
4
+
<div><input type="text" name="alt" placeholder="alt text (accessibility)"/></div>
5
+
<div><input type="text" name="title" placeholder="title text (hover)"/></div>
6
<div><input type="text" name="href" placeholder="link"/></div>
7
<div><input type="submit" value="upload"/></div>
8
</form>