tangled
alpha
login
or
join now
moth11.net
/
ttyxcvr
0
fork
atom
xcvr tui
0
fork
atom
overview
issues
pulls
pipelines
beepin and borpin
moth11.net
5 months ago
7254ae5a
fa5d4d10
+2272
-43
7 changed files
expand all
collapse all
unified
split
README.md
diff.go
go.mod
go.sum
lex
lexicons_cbor.go
types.go
main.go
+4
README.md
···
0
0
0
0
···
1
+
# tty!xcvr
2
+
3
+
talk to you! transceiver is everyone's favorite ATP application, brought to
4
+
the teletypewriter!
+233
diff.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
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 main
2
+
3
+
import ()
4
+
5
+
type EditType = int
6
+
7
+
const (
8
+
EditAdd EditType = iota
9
+
EditKeep
10
+
EditDel
11
+
EditNil
12
+
)
13
+
14
+
type Edit struct {
15
+
EditType EditType
16
+
Utf16Text []uint16
17
+
}
18
+
19
+
type Editstring struct {
20
+
EditType EditType
21
+
Text string
22
+
}
23
+
24
+
type EditSegment struct {
25
+
weight int
26
+
aidx int
27
+
bidx int
28
+
parent *EditSegment
29
+
}
30
+
31
+
type coordinate struct {
32
+
a int
33
+
b int
34
+
}
35
+
36
+
type SegmentHeap struct {
37
+
segments []*EditSegment
38
+
searched map[coordinate]bool
39
+
}
40
+
41
+
func NewSegmentHeap() SegmentHeap {
42
+
segments := make([]*EditSegment, 0, 10)
43
+
searched := make(map[coordinate]bool)
44
+
return SegmentHeap{segments, searched}
45
+
}
46
+
47
+
func (h *SegmentHeap) Add(seg *EditSegment) {
48
+
searched := h.searched[coordinate{seg.aidx, seg.bidx}]
49
+
if searched {
50
+
return
51
+
}
52
+
h.segments = append(h.segments, seg)
53
+
h.searched[coordinate{seg.aidx, seg.bidx}] = true
54
+
h.siftUp(len(h.segments) - 1)
55
+
}
56
+
57
+
func (h *SegmentHeap) PopFront() *EditSegment {
58
+
if len(h.segments) == 0 {
59
+
return nil
60
+
}
61
+
front := h.segments[0]
62
+
if len(h.segments) == 1 {
63
+
h.segments = nil
64
+
return front
65
+
}
66
+
h.segments[0] = h.segments[len(h.segments)-1]
67
+
h.segments = h.segments[:len(h.segments)-1]
68
+
h.siftDown(0)
69
+
return front
70
+
}
71
+
72
+
func (h *SegmentHeap) siftUp(idx int) {
73
+
if idx == 0 {
74
+
return
75
+
}
76
+
loweridx := idx
77
+
upperidx := (idx - 1) / 2
78
+
lower := h.segments[loweridx]
79
+
upper := h.segments[upperidx]
80
+
if lower.lighter(upper) {
81
+
h.segments[upperidx] = lower
82
+
h.segments[loweridx] = upper
83
+
h.siftUp(upperidx)
84
+
}
85
+
}
86
+
87
+
func (h *SegmentHeap) siftDown(idx int) {
88
+
upperidx := idx
89
+
var swap *EditSegment
90
+
loweridx := idx*2 + 1
91
+
lower2idx := idx*2 + 2
92
+
if loweridx < len(h.segments) && h.segments[loweridx].lighter(h.segments[upperidx]) {
93
+
swap = h.segments[upperidx]
94
+
h.segments[upperidx] = h.segments[loweridx]
95
+
h.segments[loweridx] = swap
96
+
h.siftDown(loweridx)
97
+
return
98
+
}
99
+
if lower2idx < len(h.segments) && h.segments[lower2idx].lighter(h.segments[upperidx]) {
100
+
swap = h.segments[upperidx]
101
+
h.segments[upperidx] = h.segments[lower2idx]
102
+
h.segments[lower2idx] = swap
103
+
h.siftDown(lower2idx)
104
+
return
105
+
}
106
+
107
+
}
108
+
109
+
func (seg *EditSegment) lighter(A *EditSegment) bool {
110
+
if seg.weight < A.weight {
111
+
return true
112
+
} else if seg.weight > A.weight {
113
+
return false
114
+
} else {
115
+
return seg.aidx+seg.bidx > A.aidx+A.bidx
116
+
}
117
+
}
118
+
119
+
// Diff calculates the diff between wordA and wordB as a miniaml slice of
120
+
// edits that you have to make to wordA so that you end up with wordB
121
+
func Diff(wordA []uint16, wordB []uint16) []Edit {
122
+
heap := NewSegmentHeap()
123
+
head := EditSegment{0, 0, 0, nil}
124
+
heap.Add(&head)
125
+
segment := heap.PopFront()
126
+
for !(segment.aidx == len(wordA) && segment.bidx == len(wordB)) {
127
+
if segment.aidx != len(wordA) &&
128
+
segment.bidx != len(wordB) &&
129
+
wordA[segment.aidx] == wordB[segment.bidx] {
130
+
newSegment := EditSegment{segment.weight, segment.aidx + 1, segment.bidx + 1, segment}
131
+
heap.Add(&newSegment)
132
+
}
133
+
if segment.aidx != len(wordA) {
134
+
newSegment := EditSegment{segment.weight + 1, segment.aidx + 1, segment.bidx, segment}
135
+
heap.Add(&newSegment)
136
+
}
137
+
if segment.bidx != len(wordB) {
138
+
newSegment := EditSegment{segment.weight + 1, segment.aidx, segment.bidx + 1, segment}
139
+
heap.Add(&newSegment)
140
+
}
141
+
segment = heap.PopFront()
142
+
}
143
+
prevSegment := segment.parent
144
+
edits := make([]Edit, 0)
145
+
currentEdit := Edit{EditNil, nil}
146
+
for prevSegment != nil {
147
+
diffA := prevSegment.aidx != segment.aidx
148
+
diffB := prevSegment.bidx != segment.bidx
149
+
var et EditType
150
+
var char uint16
151
+
if diffA && diffB {
152
+
et = EditKeep
153
+
char = wordA[prevSegment.aidx]
154
+
} else if diffA {
155
+
et = EditDel
156
+
char = wordA[prevSegment.aidx]
157
+
} else if diffB {
158
+
et = EditAdd
159
+
char = wordB[prevSegment.bidx]
160
+
} else {
161
+
et = EditNil
162
+
}
163
+
if currentEdit.EditType != et {
164
+
if currentEdit.EditType != EditNil {
165
+
edits = append([]Edit{currentEdit}, edits...)
166
+
}
167
+
currentEdit = Edit{et, []uint16{char}}
168
+
} else {
169
+
currentEdit.Utf16Text = append([]uint16{char}, currentEdit.Utf16Text...)
170
+
}
171
+
segment = prevSegment
172
+
prevSegment = segment.parent
173
+
}
174
+
edits = append([]Edit{currentEdit}, edits...)
175
+
return edits
176
+
}
177
+
178
+
func Diffs(wordA string, wordB string) []Editstring {
179
+
heap := NewSegmentHeap()
180
+
head := EditSegment{0, 0, 0, nil}
181
+
heap.Add(&head)
182
+
segment := heap.PopFront()
183
+
for !(segment.aidx == len(wordA) && segment.bidx == len(wordB)) {
184
+
if segment.aidx != len(wordA) &&
185
+
segment.bidx != len(wordB) &&
186
+
wordA[segment.aidx] == wordB[segment.bidx] {
187
+
newSegment := EditSegment{segment.weight, segment.aidx + 1, segment.bidx + 1, segment}
188
+
heap.Add(&newSegment)
189
+
}
190
+
if segment.aidx != len(wordA) {
191
+
newSegment := EditSegment{segment.weight + 1, segment.aidx + 1, segment.bidx, segment}
192
+
heap.Add(&newSegment)
193
+
}
194
+
if segment.bidx != len(wordB) {
195
+
newSegment := EditSegment{segment.weight + 1, segment.aidx, segment.bidx + 1, segment}
196
+
heap.Add(&newSegment)
197
+
}
198
+
segment = heap.PopFront()
199
+
}
200
+
prevSegment := segment.parent
201
+
edits := make([]Editstring, 0)
202
+
currentEdit := Editstring{EditNil, ""}
203
+
for prevSegment != nil {
204
+
diffA := prevSegment.aidx != segment.aidx
205
+
diffB := prevSegment.bidx != segment.bidx
206
+
var et EditType
207
+
var char string
208
+
if diffA && diffB {
209
+
et = EditKeep
210
+
char = string(wordA[prevSegment.aidx])
211
+
} else if diffA {
212
+
et = EditDel
213
+
char = string(wordA[prevSegment.aidx])
214
+
} else if diffB {
215
+
et = EditAdd
216
+
char = string(wordB[prevSegment.bidx])
217
+
} else {
218
+
et = EditNil
219
+
}
220
+
if currentEdit.EditType != et {
221
+
if currentEdit.EditType != EditNil {
222
+
edits = append([]Editstring{currentEdit}, edits...)
223
+
}
224
+
currentEdit = Editstring{et, char}
225
+
} else {
226
+
currentEdit.Text = char + currentEdit.Text
227
+
}
228
+
segment = prevSegment
229
+
prevSegment = segment.parent
230
+
}
231
+
edits = append([]Editstring{currentEdit}, edits...)
232
+
return edits
233
+
}
+32
-5
go.mod
···
3
go 1.24.2
4
5
require (
0
6
github.com/charmbracelet/bubbles v0.21.0
7
github.com/charmbracelet/bubbletea v1.3.10
0
0
0
0
0
0
0
8
)
9
10
require (
11
github.com/atotto/clipboard v0.1.4 // indirect
12
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
0
0
0
13
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
14
-
github.com/charmbracelet/lipgloss v1.1.0 // indirect
15
github.com/charmbracelet/x/ansi v0.10.1 // indirect
16
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
17
github.com/charmbracelet/x/term v0.2.1 // indirect
18
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
19
-
github.com/gorilla/websocket v1.5.3 // indirect
0
20
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
21
github.com/mattn/go-isatty v0.0.20 // indirect
22
github.com/mattn/go-localereader v0.0.1 // indirect
23
github.com/mattn/go-runewidth v0.0.16 // indirect
0
0
0
24
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
25
github.com/muesli/cancelreader v0.2.2 // indirect
26
github.com/muesli/termenv v0.16.0 // indirect
27
-
github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c // indirect
0
0
0
0
0
0
0
0
28
github.com/rivo/uniseg v0.4.7 // indirect
29
github.com/sahilm/fuzzy v0.1.1 // indirect
0
30
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
0
0
0
31
golang.org/x/sys v0.36.0 // indirect
32
-
golang.org/x/text v0.3.8 // indirect
33
-
google.golang.org/protobuf v1.36.6 // indirect
0
34
)
···
3
go 1.24.2
4
5
require (
6
+
github.com/bluesky-social/indigo v0.0.0-20250925152209-0f22fe8b39a8
7
github.com/charmbracelet/bubbles v0.21.0
8
github.com/charmbracelet/bubbletea v1.3.10
9
+
github.com/charmbracelet/lipgloss v1.1.0
10
+
github.com/gorilla/websocket v1.5.3
11
+
github.com/ipfs/go-cid v0.4.1
12
+
github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c
13
+
github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e
14
+
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
15
+
google.golang.org/protobuf v1.36.6
16
)
17
18
require (
19
github.com/atotto/clipboard v0.1.4 // indirect
20
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
21
+
github.com/beorn7/perks v1.0.1 // indirect
22
+
github.com/carlmjohnson/versioninfo v0.22.5 // indirect
23
+
github.com/cespare/xxhash/v2 v2.2.0 // indirect
24
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
0
25
github.com/charmbracelet/x/ansi v0.10.1 // indirect
26
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
27
github.com/charmbracelet/x/term v0.2.1 // indirect
28
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
29
+
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
30
+
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
31
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
32
github.com/mattn/go-isatty v0.0.20 // indirect
33
github.com/mattn/go-localereader v0.0.1 // indirect
34
github.com/mattn/go-runewidth v0.0.16 // indirect
35
+
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
36
+
github.com/minio/sha256-simd v1.0.1 // indirect
37
+
github.com/mr-tron/base58 v1.2.0 // indirect
38
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
39
github.com/muesli/cancelreader v0.2.2 // indirect
40
github.com/muesli/termenv v0.16.0 // indirect
41
+
github.com/multiformats/go-base32 v0.1.0 // indirect
42
+
github.com/multiformats/go-base36 v0.2.0 // indirect
43
+
github.com/multiformats/go-multibase v0.2.0 // indirect
44
+
github.com/multiformats/go-multihash v0.2.3 // indirect
45
+
github.com/multiformats/go-varint v0.0.7 // indirect
46
+
github.com/prometheus/client_golang v1.17.0 // indirect
47
+
github.com/prometheus/client_model v0.5.0 // indirect
48
+
github.com/prometheus/common v0.45.0 // indirect
49
+
github.com/prometheus/procfs v0.12.0 // indirect
50
github.com/rivo/uniseg v0.4.7 // indirect
51
github.com/sahilm/fuzzy v0.1.1 // indirect
52
+
github.com/spaolacci/murmur3 v1.1.0 // indirect
53
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
54
+
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
55
+
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
56
+
golang.org/x/crypto v0.21.0 // indirect
57
golang.org/x/sys v0.36.0 // indirect
58
+
golang.org/x/text v0.14.0 // indirect
59
+
golang.org/x/time v0.3.0 // indirect
60
+
lukechampine.com/blake3 v1.2.1 // indirect
61
)
+127
-4
go.sum
···
4
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
5
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
6
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
0
0
0
0
0
0
0
0
7
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
8
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
9
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
···
20
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
21
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
22
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
0
0
23
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
24
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
0
0
0
0
0
0
0
0
0
0
0
0
25
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
26
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
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
27
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
28
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
29
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
···
34
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
35
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
36
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
0
0
0
0
0
0
37
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
38
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
39
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
40
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
41
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
42
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
43
github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c h1:t33xVlfSwvB80nj1jroRXUaq/RTgjWwD4l7p/ISatUQ=
44
github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw=
45
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
···
47
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
48
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
49
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
0
0
0
0
0
0
50
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
51
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
52
-
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
53
-
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
54
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
0
55
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
56
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
57
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
58
-
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
59
-
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
0
0
0
0
60
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
61
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
0
0
0
0
···
4
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
5
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
6
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
7
+
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
8
+
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
9
+
github.com/bluesky-social/indigo v0.0.0-20250925152209-0f22fe8b39a8 h1:+YD75cZtvj0uFVOjb8XglqJ4Ev4UFKyAvzR3TOMREW0=
10
+
github.com/bluesky-social/indigo v0.0.0-20250925152209-0f22fe8b39a8/go.mod h1:n6QE1NDPFoi7PRbMUZmc2y7FibCqiVU4ePpsvhHUBR8=
11
+
github.com/carlmjohnson/versioninfo v0.22.5 h1:O00sjOLUAFxYQjlN/bzYTuZiS0y6fWDQjMRvwtKgwwc=
12
+
github.com/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8=
13
+
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
14
+
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
15
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
16
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
17
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
···
28
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
29
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
30
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
31
+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
32
+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
33
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
34
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
35
+
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
36
+
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
37
+
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
38
+
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
39
+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
40
+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
41
+
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
42
+
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
43
+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
44
+
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
45
+
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
46
+
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
47
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
48
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
49
+
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
50
+
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
51
+
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
52
+
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
53
+
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
54
+
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
55
+
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
56
+
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
57
+
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
58
+
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
59
+
github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
60
+
github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
61
+
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
62
+
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
63
+
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
64
+
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
65
+
github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
66
+
github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
67
+
github.com/ipfs/go-ipfs-ds-help v1.1.1 h1:B5UJOH52IbcfS56+Ul+sv8jnIV10lbjLF5eOO0C66Nw=
68
+
github.com/ipfs/go-ipfs-ds-help v1.1.1/go.mod h1:75vrVCkSdSFidJscs8n4W+77AtTpCIAdDGAwjitJMIo=
69
+
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
70
+
github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
71
+
github.com/ipfs/go-ipld-cbor v0.1.0 h1:dx0nS0kILVivGhfWuB6dUpMa/LAwElHPw1yOGYopoYs=
72
+
github.com/ipfs/go-ipld-cbor v0.1.0/go.mod h1:U2aYlmVrJr2wsUBU67K4KgepApSZddGRDWBYR0H4sCk=
73
+
github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
74
+
github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
75
+
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
76
+
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
77
+
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
78
+
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
79
+
github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg=
80
+
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
81
+
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
82
+
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
83
+
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
84
+
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
85
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
86
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
87
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
···
92
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
93
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
94
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
95
+
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
96
+
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
97
+
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
98
+
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
99
+
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
100
+
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
101
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
102
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
103
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
104
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
105
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
106
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
107
+
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
108
+
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
109
+
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
110
+
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
111
+
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
112
+
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
113
+
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
114
+
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
115
+
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
116
+
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
117
+
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
118
+
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
119
+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
120
+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
121
+
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0=
122
+
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
123
+
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
124
+
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
125
+
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
126
+
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
127
+
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
128
+
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
129
+
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
130
+
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
131
github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c h1:t33xVlfSwvB80nj1jroRXUaq/RTgjWwD4l7p/ISatUQ=
132
github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw=
133
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
···
135
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
136
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
137
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
138
+
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
139
+
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
140
+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
141
+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
142
+
github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e h1:28X54ciEwwUxyHn9yrZfl5ojgF4CBNLWX7LR0rvBkf4=
143
+
github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so=
144
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
145
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
146
+
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA=
147
+
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8=
148
+
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q=
149
+
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I=
150
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
151
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
152
+
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
153
+
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
154
+
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
155
+
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
156
+
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
157
+
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
158
+
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
159
+
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
160
+
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
161
+
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
162
+
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
163
+
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
164
+
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
165
+
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
166
+
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
167
+
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
168
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
169
+
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
170
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
171
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
172
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
173
+
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
174
+
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
175
+
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
176
+
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
177
+
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
178
+
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
179
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
180
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
181
+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
182
+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
183
+
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
184
+
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
+1207
lex/lexicons_cbor.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
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
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
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
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
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
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
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT.
2
+
3
+
package lex
4
+
5
+
import (
6
+
"fmt"
7
+
"io"
8
+
"math"
9
+
"sort"
10
+
11
+
util "github.com/bluesky-social/indigo/lex/util"
12
+
cid "github.com/ipfs/go-cid"
13
+
cbg "github.com/whyrusleeping/cbor-gen"
14
+
xerrors "golang.org/x/xerrors"
15
+
)
16
+
17
+
var _ = xerrors.Errorf
18
+
var _ = cid.Undef
19
+
var _ = math.E
20
+
var _ = sort.Sort
21
+
22
+
func (t *ProfileRecord) MarshalCBOR(w io.Writer) error {
23
+
if t == nil {
24
+
_, err := w.Write(cbg.CborNull)
25
+
return err
26
+
}
27
+
28
+
cw := cbg.NewCborWriter(w)
29
+
fieldCount := 6
30
+
31
+
if t.DisplayName == nil {
32
+
fieldCount--
33
+
}
34
+
35
+
if t.DefaultNick == nil {
36
+
fieldCount--
37
+
}
38
+
39
+
if t.Status == nil {
40
+
fieldCount--
41
+
}
42
+
43
+
if t.Avatar == nil {
44
+
fieldCount--
45
+
}
46
+
47
+
if t.Color == nil {
48
+
fieldCount--
49
+
}
50
+
51
+
if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
52
+
return err
53
+
}
54
+
55
+
// t.LexiconTypeID (string) (string)
56
+
if len("$type") > 8192 {
57
+
return xerrors.Errorf("Value in field \"$type\" was too long")
58
+
}
59
+
60
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil {
61
+
return err
62
+
}
63
+
if _, err := cw.WriteString(string("$type")); err != nil {
64
+
return err
65
+
}
66
+
67
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("org.xcvr.actor.profile"))); err != nil {
68
+
return err
69
+
}
70
+
if _, err := cw.WriteString(string("org.xcvr.actor.profile")); err != nil {
71
+
return err
72
+
}
73
+
74
+
// t.Color (uint64) (uint64)
75
+
if t.Color != nil {
76
+
77
+
if len("color") > 8192 {
78
+
return xerrors.Errorf("Value in field \"color\" was too long")
79
+
}
80
+
81
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("color"))); err != nil {
82
+
return err
83
+
}
84
+
if _, err := cw.WriteString(string("color")); err != nil {
85
+
return err
86
+
}
87
+
88
+
if t.Color == nil {
89
+
if _, err := cw.Write(cbg.CborNull); err != nil {
90
+
return err
91
+
}
92
+
} else {
93
+
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.Color)); err != nil {
94
+
return err
95
+
}
96
+
}
97
+
98
+
}
99
+
100
+
// t.Avatar (util.LexBlob) (struct)
101
+
if t.Avatar != nil {
102
+
103
+
if len("avatar") > 8192 {
104
+
return xerrors.Errorf("Value in field \"avatar\" was too long")
105
+
}
106
+
107
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("avatar"))); err != nil {
108
+
return err
109
+
}
110
+
if _, err := cw.WriteString(string("avatar")); err != nil {
111
+
return err
112
+
}
113
+
114
+
if err := t.Avatar.MarshalCBOR(cw); err != nil {
115
+
return err
116
+
}
117
+
}
118
+
119
+
// t.Status (string) (string)
120
+
if t.Status != nil {
121
+
122
+
if len("status") > 8192 {
123
+
return xerrors.Errorf("Value in field \"status\" was too long")
124
+
}
125
+
126
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("status"))); err != nil {
127
+
return err
128
+
}
129
+
if _, err := cw.WriteString(string("status")); err != nil {
130
+
return err
131
+
}
132
+
133
+
if t.Status == nil {
134
+
if _, err := cw.Write(cbg.CborNull); err != nil {
135
+
return err
136
+
}
137
+
} else {
138
+
if len(*t.Status) > 8192 {
139
+
return xerrors.Errorf("Value in field t.Status was too long")
140
+
}
141
+
142
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Status))); err != nil {
143
+
return err
144
+
}
145
+
if _, err := cw.WriteString(string(*t.Status)); err != nil {
146
+
return err
147
+
}
148
+
}
149
+
}
150
+
151
+
// t.DefaultNick (string) (string)
152
+
if t.DefaultNick != nil {
153
+
154
+
if len("defaultNick") > 8192 {
155
+
return xerrors.Errorf("Value in field \"defaultNick\" was too long")
156
+
}
157
+
158
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("defaultNick"))); err != nil {
159
+
return err
160
+
}
161
+
if _, err := cw.WriteString(string("defaultNick")); err != nil {
162
+
return err
163
+
}
164
+
165
+
if t.DefaultNick == nil {
166
+
if _, err := cw.Write(cbg.CborNull); err != nil {
167
+
return err
168
+
}
169
+
} else {
170
+
if len(*t.DefaultNick) > 8192 {
171
+
return xerrors.Errorf("Value in field t.DefaultNick was too long")
172
+
}
173
+
174
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.DefaultNick))); err != nil {
175
+
return err
176
+
}
177
+
if _, err := cw.WriteString(string(*t.DefaultNick)); err != nil {
178
+
return err
179
+
}
180
+
}
181
+
}
182
+
183
+
// t.DisplayName (string) (string)
184
+
if t.DisplayName != nil {
185
+
186
+
if len("displayName") > 8192 {
187
+
return xerrors.Errorf("Value in field \"displayName\" was too long")
188
+
}
189
+
190
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("displayName"))); err != nil {
191
+
return err
192
+
}
193
+
if _, err := cw.WriteString(string("displayName")); err != nil {
194
+
return err
195
+
}
196
+
197
+
if t.DisplayName == nil {
198
+
if _, err := cw.Write(cbg.CborNull); err != nil {
199
+
return err
200
+
}
201
+
} else {
202
+
if len(*t.DisplayName) > 8192 {
203
+
return xerrors.Errorf("Value in field t.DisplayName was too long")
204
+
}
205
+
206
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.DisplayName))); err != nil {
207
+
return err
208
+
}
209
+
if _, err := cw.WriteString(string(*t.DisplayName)); err != nil {
210
+
return err
211
+
}
212
+
}
213
+
}
214
+
return nil
215
+
}
216
+
217
+
func (t *ProfileRecord) UnmarshalCBOR(r io.Reader) (err error) {
218
+
*t = ProfileRecord{}
219
+
220
+
cr := cbg.NewCborReader(r)
221
+
222
+
maj, extra, err := cr.ReadHeader()
223
+
if err != nil {
224
+
return err
225
+
}
226
+
defer func() {
227
+
if err == io.EOF {
228
+
err = io.ErrUnexpectedEOF
229
+
}
230
+
}()
231
+
232
+
if maj != cbg.MajMap {
233
+
return fmt.Errorf("cbor input should be of type map")
234
+
}
235
+
236
+
if extra > cbg.MaxLength {
237
+
return fmt.Errorf("ProfileRecord: map struct too large (%d)", extra)
238
+
}
239
+
240
+
n := extra
241
+
242
+
nameBuf := make([]byte, 11)
243
+
for i := uint64(0); i < n; i++ {
244
+
nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192)
245
+
if err != nil {
246
+
return err
247
+
}
248
+
249
+
if !ok {
250
+
// Field doesn't exist on this type, so ignore it
251
+
if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
252
+
return err
253
+
}
254
+
continue
255
+
}
256
+
257
+
switch string(nameBuf[:nameLen]) {
258
+
// t.LexiconTypeID (string) (string)
259
+
case "$type":
260
+
261
+
{
262
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
263
+
if err != nil {
264
+
return err
265
+
}
266
+
267
+
t.LexiconTypeID = string(sval)
268
+
}
269
+
// t.Color (uint64) (uint64)
270
+
case "color":
271
+
272
+
{
273
+
274
+
b, err := cr.ReadByte()
275
+
if err != nil {
276
+
return err
277
+
}
278
+
if b != cbg.CborNull[0] {
279
+
if err := cr.UnreadByte(); err != nil {
280
+
return err
281
+
}
282
+
maj, extra, err = cr.ReadHeader()
283
+
if err != nil {
284
+
return err
285
+
}
286
+
if maj != cbg.MajUnsignedInt {
287
+
return fmt.Errorf("wrong type for uint64 field")
288
+
}
289
+
typed := uint64(extra)
290
+
t.Color = &typed
291
+
}
292
+
293
+
}
294
+
// t.Avatar (util.LexBlob) (struct)
295
+
case "avatar":
296
+
297
+
{
298
+
299
+
b, err := cr.ReadByte()
300
+
if err != nil {
301
+
return err
302
+
}
303
+
if b != cbg.CborNull[0] {
304
+
if err := cr.UnreadByte(); err != nil {
305
+
return err
306
+
}
307
+
t.Avatar = new(util.LexBlob)
308
+
if err := t.Avatar.UnmarshalCBOR(cr); err != nil {
309
+
return xerrors.Errorf("unmarshaling t.Avatar pointer: %w", err)
310
+
}
311
+
}
312
+
313
+
}
314
+
// t.Status (string) (string)
315
+
case "status":
316
+
317
+
{
318
+
b, err := cr.ReadByte()
319
+
if err != nil {
320
+
return err
321
+
}
322
+
if b != cbg.CborNull[0] {
323
+
if err := cr.UnreadByte(); err != nil {
324
+
return err
325
+
}
326
+
327
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
328
+
if err != nil {
329
+
return err
330
+
}
331
+
332
+
t.Status = (*string)(&sval)
333
+
}
334
+
}
335
+
// t.DefaultNick (string) (string)
336
+
case "defaultNick":
337
+
338
+
{
339
+
b, err := cr.ReadByte()
340
+
if err != nil {
341
+
return err
342
+
}
343
+
if b != cbg.CborNull[0] {
344
+
if err := cr.UnreadByte(); err != nil {
345
+
return err
346
+
}
347
+
348
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
349
+
if err != nil {
350
+
return err
351
+
}
352
+
353
+
t.DefaultNick = (*string)(&sval)
354
+
}
355
+
}
356
+
// t.DisplayName (string) (string)
357
+
case "displayName":
358
+
359
+
{
360
+
b, err := cr.ReadByte()
361
+
if err != nil {
362
+
return err
363
+
}
364
+
if b != cbg.CborNull[0] {
365
+
if err := cr.UnreadByte(); err != nil {
366
+
return err
367
+
}
368
+
369
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
370
+
if err != nil {
371
+
return err
372
+
}
373
+
374
+
t.DisplayName = (*string)(&sval)
375
+
}
376
+
}
377
+
378
+
default:
379
+
// Field doesn't exist on this type, so ignore it
380
+
if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
381
+
return err
382
+
}
383
+
}
384
+
}
385
+
386
+
return nil
387
+
}
388
+
func (t *ChannelRecord) MarshalCBOR(w io.Writer) error {
389
+
if t == nil {
390
+
_, err := w.Write(cbg.CborNull)
391
+
return err
392
+
}
393
+
394
+
cw := cbg.NewCborWriter(w)
395
+
fieldCount := 5
396
+
397
+
if t.Topic == nil {
398
+
fieldCount--
399
+
}
400
+
401
+
if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
402
+
return err
403
+
}
404
+
405
+
// t.Host (string) (string)
406
+
if len("host") > 8192 {
407
+
return xerrors.Errorf("Value in field \"host\" was too long")
408
+
}
409
+
410
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("host"))); err != nil {
411
+
return err
412
+
}
413
+
if _, err := cw.WriteString(string("host")); err != nil {
414
+
return err
415
+
}
416
+
417
+
if len(t.Host) > 8192 {
418
+
return xerrors.Errorf("Value in field t.Host was too long")
419
+
}
420
+
421
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Host))); err != nil {
422
+
return err
423
+
}
424
+
if _, err := cw.WriteString(string(t.Host)); err != nil {
425
+
return err
426
+
}
427
+
428
+
// t.LexiconTypeID (string) (string)
429
+
if len("$type") > 8192 {
430
+
return xerrors.Errorf("Value in field \"$type\" was too long")
431
+
}
432
+
433
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil {
434
+
return err
435
+
}
436
+
if _, err := cw.WriteString(string("$type")); err != nil {
437
+
return err
438
+
}
439
+
440
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("org.xcvr.feed.channel"))); err != nil {
441
+
return err
442
+
}
443
+
if _, err := cw.WriteString(string("org.xcvr.feed.channel")); err != nil {
444
+
return err
445
+
}
446
+
447
+
// t.Title (string) (string)
448
+
if len("title") > 8192 {
449
+
return xerrors.Errorf("Value in field \"title\" was too long")
450
+
}
451
+
452
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("title"))); err != nil {
453
+
return err
454
+
}
455
+
if _, err := cw.WriteString(string("title")); err != nil {
456
+
return err
457
+
}
458
+
459
+
if len(t.Title) > 8192 {
460
+
return xerrors.Errorf("Value in field t.Title was too long")
461
+
}
462
+
463
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Title))); err != nil {
464
+
return err
465
+
}
466
+
if _, err := cw.WriteString(string(t.Title)); err != nil {
467
+
return err
468
+
}
469
+
470
+
// t.Topic (string) (string)
471
+
if t.Topic != nil {
472
+
473
+
if len("topic") > 8192 {
474
+
return xerrors.Errorf("Value in field \"topic\" was too long")
475
+
}
476
+
477
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("topic"))); err != nil {
478
+
return err
479
+
}
480
+
if _, err := cw.WriteString(string("topic")); err != nil {
481
+
return err
482
+
}
483
+
484
+
if t.Topic == nil {
485
+
if _, err := cw.Write(cbg.CborNull); err != nil {
486
+
return err
487
+
}
488
+
} else {
489
+
if len(*t.Topic) > 8192 {
490
+
return xerrors.Errorf("Value in field t.Topic was too long")
491
+
}
492
+
493
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Topic))); err != nil {
494
+
return err
495
+
}
496
+
if _, err := cw.WriteString(string(*t.Topic)); err != nil {
497
+
return err
498
+
}
499
+
}
500
+
}
501
+
502
+
// t.CreatedAt (string) (string)
503
+
if len("createdAt") > 8192 {
504
+
return xerrors.Errorf("Value in field \"createdAt\" was too long")
505
+
}
506
+
507
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("createdAt"))); err != nil {
508
+
return err
509
+
}
510
+
if _, err := cw.WriteString(string("createdAt")); err != nil {
511
+
return err
512
+
}
513
+
514
+
if len(t.CreatedAt) > 8192 {
515
+
return xerrors.Errorf("Value in field t.CreatedAt was too long")
516
+
}
517
+
518
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.CreatedAt))); err != nil {
519
+
return err
520
+
}
521
+
if _, err := cw.WriteString(string(t.CreatedAt)); err != nil {
522
+
return err
523
+
}
524
+
return nil
525
+
}
526
+
527
+
func (t *ChannelRecord) UnmarshalCBOR(r io.Reader) (err error) {
528
+
*t = ChannelRecord{}
529
+
530
+
cr := cbg.NewCborReader(r)
531
+
532
+
maj, extra, err := cr.ReadHeader()
533
+
if err != nil {
534
+
return err
535
+
}
536
+
defer func() {
537
+
if err == io.EOF {
538
+
err = io.ErrUnexpectedEOF
539
+
}
540
+
}()
541
+
542
+
if maj != cbg.MajMap {
543
+
return fmt.Errorf("cbor input should be of type map")
544
+
}
545
+
546
+
if extra > cbg.MaxLength {
547
+
return fmt.Errorf("ChannelRecord: map struct too large (%d)", extra)
548
+
}
549
+
550
+
n := extra
551
+
552
+
nameBuf := make([]byte, 9)
553
+
for i := uint64(0); i < n; i++ {
554
+
nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192)
555
+
if err != nil {
556
+
return err
557
+
}
558
+
559
+
if !ok {
560
+
// Field doesn't exist on this type, so ignore it
561
+
if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
562
+
return err
563
+
}
564
+
continue
565
+
}
566
+
567
+
switch string(nameBuf[:nameLen]) {
568
+
// t.Host (string) (string)
569
+
case "host":
570
+
571
+
{
572
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
573
+
if err != nil {
574
+
return err
575
+
}
576
+
577
+
t.Host = string(sval)
578
+
}
579
+
// t.LexiconTypeID (string) (string)
580
+
case "$type":
581
+
582
+
{
583
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
584
+
if err != nil {
585
+
return err
586
+
}
587
+
588
+
t.LexiconTypeID = string(sval)
589
+
}
590
+
// t.Title (string) (string)
591
+
case "title":
592
+
593
+
{
594
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
595
+
if err != nil {
596
+
return err
597
+
}
598
+
599
+
t.Title = string(sval)
600
+
}
601
+
// t.Topic (string) (string)
602
+
case "topic":
603
+
604
+
{
605
+
b, err := cr.ReadByte()
606
+
if err != nil {
607
+
return err
608
+
}
609
+
if b != cbg.CborNull[0] {
610
+
if err := cr.UnreadByte(); err != nil {
611
+
return err
612
+
}
613
+
614
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
615
+
if err != nil {
616
+
return err
617
+
}
618
+
619
+
t.Topic = (*string)(&sval)
620
+
}
621
+
}
622
+
// t.CreatedAt (string) (string)
623
+
case "createdAt":
624
+
625
+
{
626
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
627
+
if err != nil {
628
+
return err
629
+
}
630
+
631
+
t.CreatedAt = string(sval)
632
+
}
633
+
634
+
default:
635
+
// Field doesn't exist on this type, so ignore it
636
+
if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
637
+
return err
638
+
}
639
+
}
640
+
}
641
+
642
+
return nil
643
+
}
644
+
func (t *MessageRecord) MarshalCBOR(w io.Writer) error {
645
+
if t == nil {
646
+
_, err := w.Write(cbg.CborNull)
647
+
return err
648
+
}
649
+
650
+
cw := cbg.NewCborWriter(w)
651
+
fieldCount := 6
652
+
653
+
if t.Nick == nil {
654
+
fieldCount--
655
+
}
656
+
657
+
if t.Color == nil {
658
+
fieldCount--
659
+
}
660
+
661
+
if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
662
+
return err
663
+
}
664
+
665
+
// t.Body (string) (string)
666
+
if len("body") > 8192 {
667
+
return xerrors.Errorf("Value in field \"body\" was too long")
668
+
}
669
+
670
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("body"))); err != nil {
671
+
return err
672
+
}
673
+
if _, err := cw.WriteString(string("body")); err != nil {
674
+
return err
675
+
}
676
+
677
+
if len(t.Body) > 8192 {
678
+
return xerrors.Errorf("Value in field t.Body was too long")
679
+
}
680
+
681
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Body))); err != nil {
682
+
return err
683
+
}
684
+
if _, err := cw.WriteString(string(t.Body)); err != nil {
685
+
return err
686
+
}
687
+
688
+
// t.Nick (string) (string)
689
+
if t.Nick != nil {
690
+
691
+
if len("nick") > 8192 {
692
+
return xerrors.Errorf("Value in field \"nick\" was too long")
693
+
}
694
+
695
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("nick"))); err != nil {
696
+
return err
697
+
}
698
+
if _, err := cw.WriteString(string("nick")); err != nil {
699
+
return err
700
+
}
701
+
702
+
if t.Nick == nil {
703
+
if _, err := cw.Write(cbg.CborNull); err != nil {
704
+
return err
705
+
}
706
+
} else {
707
+
if len(*t.Nick) > 8192 {
708
+
return xerrors.Errorf("Value in field t.Nick was too long")
709
+
}
710
+
711
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Nick))); err != nil {
712
+
return err
713
+
}
714
+
if _, err := cw.WriteString(string(*t.Nick)); err != nil {
715
+
return err
716
+
}
717
+
}
718
+
}
719
+
720
+
// t.LexiconTypeID (string) (string)
721
+
if len("$type") > 8192 {
722
+
return xerrors.Errorf("Value in field \"$type\" was too long")
723
+
}
724
+
725
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil {
726
+
return err
727
+
}
728
+
if _, err := cw.WriteString(string("$type")); err != nil {
729
+
return err
730
+
}
731
+
732
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("org.xcvr.lrc.message"))); err != nil {
733
+
return err
734
+
}
735
+
if _, err := cw.WriteString(string("org.xcvr.lrc.message")); err != nil {
736
+
return err
737
+
}
738
+
739
+
// t.Color (uint64) (uint64)
740
+
if t.Color != nil {
741
+
742
+
if len("color") > 8192 {
743
+
return xerrors.Errorf("Value in field \"color\" was too long")
744
+
}
745
+
746
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("color"))); err != nil {
747
+
return err
748
+
}
749
+
if _, err := cw.WriteString(string("color")); err != nil {
750
+
return err
751
+
}
752
+
753
+
if t.Color == nil {
754
+
if _, err := cw.Write(cbg.CborNull); err != nil {
755
+
return err
756
+
}
757
+
} else {
758
+
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.Color)); err != nil {
759
+
return err
760
+
}
761
+
}
762
+
763
+
}
764
+
765
+
// t.PostedAt (string) (string)
766
+
if len("postedAt") > 8192 {
767
+
return xerrors.Errorf("Value in field \"postedAt\" was too long")
768
+
}
769
+
770
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("postedAt"))); err != nil {
771
+
return err
772
+
}
773
+
if _, err := cw.WriteString(string("postedAt")); err != nil {
774
+
return err
775
+
}
776
+
777
+
if len(t.PostedAt) > 8192 {
778
+
return xerrors.Errorf("Value in field t.PostedAt was too long")
779
+
}
780
+
781
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.PostedAt))); err != nil {
782
+
return err
783
+
}
784
+
if _, err := cw.WriteString(string(t.PostedAt)); err != nil {
785
+
return err
786
+
}
787
+
788
+
// t.SignetURI (string) (string)
789
+
if len("signetURI") > 8192 {
790
+
return xerrors.Errorf("Value in field \"signetURI\" was too long")
791
+
}
792
+
793
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("signetURI"))); err != nil {
794
+
return err
795
+
}
796
+
if _, err := cw.WriteString(string("signetURI")); err != nil {
797
+
return err
798
+
}
799
+
800
+
if len(t.SignetURI) > 8192 {
801
+
return xerrors.Errorf("Value in field t.SignetURI was too long")
802
+
}
803
+
804
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.SignetURI))); err != nil {
805
+
return err
806
+
}
807
+
if _, err := cw.WriteString(string(t.SignetURI)); err != nil {
808
+
return err
809
+
}
810
+
return nil
811
+
}
812
+
813
+
func (t *MessageRecord) UnmarshalCBOR(r io.Reader) (err error) {
814
+
*t = MessageRecord{}
815
+
816
+
cr := cbg.NewCborReader(r)
817
+
818
+
maj, extra, err := cr.ReadHeader()
819
+
if err != nil {
820
+
return err
821
+
}
822
+
defer func() {
823
+
if err == io.EOF {
824
+
err = io.ErrUnexpectedEOF
825
+
}
826
+
}()
827
+
828
+
if maj != cbg.MajMap {
829
+
return fmt.Errorf("cbor input should be of type map")
830
+
}
831
+
832
+
if extra > cbg.MaxLength {
833
+
return fmt.Errorf("MessageRecord: map struct too large (%d)", extra)
834
+
}
835
+
836
+
n := extra
837
+
838
+
nameBuf := make([]byte, 9)
839
+
for i := uint64(0); i < n; i++ {
840
+
nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192)
841
+
if err != nil {
842
+
return err
843
+
}
844
+
845
+
if !ok {
846
+
// Field doesn't exist on this type, so ignore it
847
+
if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
848
+
return err
849
+
}
850
+
continue
851
+
}
852
+
853
+
switch string(nameBuf[:nameLen]) {
854
+
// t.Body (string) (string)
855
+
case "body":
856
+
857
+
{
858
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
859
+
if err != nil {
860
+
return err
861
+
}
862
+
863
+
t.Body = string(sval)
864
+
}
865
+
// t.Nick (string) (string)
866
+
case "nick":
867
+
868
+
{
869
+
b, err := cr.ReadByte()
870
+
if err != nil {
871
+
return err
872
+
}
873
+
if b != cbg.CborNull[0] {
874
+
if err := cr.UnreadByte(); err != nil {
875
+
return err
876
+
}
877
+
878
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
879
+
if err != nil {
880
+
return err
881
+
}
882
+
883
+
t.Nick = (*string)(&sval)
884
+
}
885
+
}
886
+
// t.LexiconTypeID (string) (string)
887
+
case "$type":
888
+
889
+
{
890
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
891
+
if err != nil {
892
+
return err
893
+
}
894
+
895
+
t.LexiconTypeID = string(sval)
896
+
}
897
+
// t.Color (uint64) (uint64)
898
+
case "color":
899
+
900
+
{
901
+
902
+
b, err := cr.ReadByte()
903
+
if err != nil {
904
+
return err
905
+
}
906
+
if b != cbg.CborNull[0] {
907
+
if err := cr.UnreadByte(); err != nil {
908
+
return err
909
+
}
910
+
maj, extra, err = cr.ReadHeader()
911
+
if err != nil {
912
+
return err
913
+
}
914
+
if maj != cbg.MajUnsignedInt {
915
+
return fmt.Errorf("wrong type for uint64 field")
916
+
}
917
+
typed := uint64(extra)
918
+
t.Color = &typed
919
+
}
920
+
921
+
}
922
+
// t.PostedAt (string) (string)
923
+
case "postedAt":
924
+
925
+
{
926
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
927
+
if err != nil {
928
+
return err
929
+
}
930
+
931
+
t.PostedAt = string(sval)
932
+
}
933
+
// t.SignetURI (string) (string)
934
+
case "signetURI":
935
+
936
+
{
937
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
938
+
if err != nil {
939
+
return err
940
+
}
941
+
942
+
t.SignetURI = string(sval)
943
+
}
944
+
945
+
default:
946
+
// Field doesn't exist on this type, so ignore it
947
+
if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
948
+
return err
949
+
}
950
+
}
951
+
}
952
+
953
+
return nil
954
+
}
955
+
func (t *SignetRecord) MarshalCBOR(w io.Writer) error {
956
+
if t == nil {
957
+
_, err := w.Write(cbg.CborNull)
958
+
return err
959
+
}
960
+
961
+
cw := cbg.NewCborWriter(w)
962
+
fieldCount := 5
963
+
964
+
if t.StartedAt == nil {
965
+
fieldCount--
966
+
}
967
+
968
+
if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
969
+
return err
970
+
}
971
+
972
+
// t.Author (string) (string)
973
+
if len("nick") > 8192 {
974
+
return xerrors.Errorf("Value in field \"nick\" was too long")
975
+
}
976
+
977
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("nick"))); err != nil {
978
+
return err
979
+
}
980
+
if _, err := cw.WriteString(string("nick")); err != nil {
981
+
return err
982
+
}
983
+
984
+
if len(t.AuthorHandle) > 8192 {
985
+
return xerrors.Errorf("Value in field t.Author was too long")
986
+
}
987
+
988
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.AuthorHandle))); err != nil {
989
+
return err
990
+
}
991
+
if _, err := cw.WriteString(string(t.AuthorHandle)); err != nil {
992
+
return err
993
+
}
994
+
995
+
// t.LexiconTypeID (string) (string)
996
+
if len("$type") > 8192 {
997
+
return xerrors.Errorf("Value in field \"$type\" was too long")
998
+
}
999
+
1000
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil {
1001
+
return err
1002
+
}
1003
+
if _, err := cw.WriteString(string("$type")); err != nil {
1004
+
return err
1005
+
}
1006
+
1007
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("org.xcvr.lrc.signet"))); err != nil {
1008
+
return err
1009
+
}
1010
+
if _, err := cw.WriteString(string("org.xcvr.lrc.signet")); err != nil {
1011
+
return err
1012
+
}
1013
+
1014
+
// t.LRCID (uint64) (uint64)
1015
+
if len("lrcID") > 8192 {
1016
+
return xerrors.Errorf("Value in field \"lrcID\" was too long")
1017
+
}
1018
+
1019
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("lrcID"))); err != nil {
1020
+
return err
1021
+
}
1022
+
if _, err := cw.WriteString(string("lrcID")); err != nil {
1023
+
return err
1024
+
}
1025
+
1026
+
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.LRCID)); err != nil {
1027
+
return err
1028
+
}
1029
+
1030
+
// t.StartedAt (string) (string)
1031
+
if t.StartedAt != nil {
1032
+
1033
+
if len("startedAt") > 8192 {
1034
+
return xerrors.Errorf("Value in field \"startedAt\" was too long")
1035
+
}
1036
+
1037
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("startedAt"))); err != nil {
1038
+
return err
1039
+
}
1040
+
if _, err := cw.WriteString(string("startedAt")); err != nil {
1041
+
return err
1042
+
}
1043
+
1044
+
if t.StartedAt == nil {
1045
+
if _, err := cw.Write(cbg.CborNull); err != nil {
1046
+
return err
1047
+
}
1048
+
} else {
1049
+
if len(*t.StartedAt) > 8192 {
1050
+
return xerrors.Errorf("Value in field t.StartedAt was too long")
1051
+
}
1052
+
1053
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.StartedAt))); err != nil {
1054
+
return err
1055
+
}
1056
+
if _, err := cw.WriteString(string(*t.StartedAt)); err != nil {
1057
+
return err
1058
+
}
1059
+
}
1060
+
}
1061
+
1062
+
// t.ChannelURI (string) (string)
1063
+
if len("channelURI") > 8192 {
1064
+
return xerrors.Errorf("Value in field \"channelURI\" was too long")
1065
+
}
1066
+
1067
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("channelURI"))); err != nil {
1068
+
return err
1069
+
}
1070
+
if _, err := cw.WriteString(string("channelURI")); err != nil {
1071
+
return err
1072
+
}
1073
+
1074
+
if len(t.ChannelURI) > 8192 {
1075
+
return xerrors.Errorf("Value in field t.ChannelURI was too long")
1076
+
}
1077
+
1078
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.ChannelURI))); err != nil {
1079
+
return err
1080
+
}
1081
+
if _, err := cw.WriteString(string(t.ChannelURI)); err != nil {
1082
+
return err
1083
+
}
1084
+
return nil
1085
+
}
1086
+
1087
+
func (t *SignetRecord) UnmarshalCBOR(r io.Reader) (err error) {
1088
+
*t = SignetRecord{}
1089
+
1090
+
cr := cbg.NewCborReader(r)
1091
+
1092
+
maj, extra, err := cr.ReadHeader()
1093
+
if err != nil {
1094
+
return err
1095
+
}
1096
+
defer func() {
1097
+
if err == io.EOF {
1098
+
err = io.ErrUnexpectedEOF
1099
+
}
1100
+
}()
1101
+
1102
+
if maj != cbg.MajMap {
1103
+
return fmt.Errorf("cbor input should be of type map")
1104
+
}
1105
+
1106
+
if extra > cbg.MaxLength {
1107
+
return fmt.Errorf("SignetRecord: map struct too large (%d)", extra)
1108
+
}
1109
+
1110
+
n := extra
1111
+
1112
+
nameBuf := make([]byte, 10)
1113
+
for i := uint64(0); i < n; i++ {
1114
+
nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 8192)
1115
+
if err != nil {
1116
+
return err
1117
+
}
1118
+
1119
+
if !ok {
1120
+
// Field doesn't exist on this type, so ignore it
1121
+
if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
1122
+
return err
1123
+
}
1124
+
continue
1125
+
}
1126
+
1127
+
switch string(nameBuf[:nameLen]) {
1128
+
// t.Author (string) (string)
1129
+
case "authorHandle":
1130
+
1131
+
{
1132
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
1133
+
if err != nil {
1134
+
return err
1135
+
}
1136
+
1137
+
t.AuthorHandle = string(sval)
1138
+
}
1139
+
// t.LexiconTypeID (string) (string)
1140
+
case "$type":
1141
+
1142
+
{
1143
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
1144
+
if err != nil {
1145
+
return err
1146
+
}
1147
+
1148
+
t.LexiconTypeID = string(sval)
1149
+
}
1150
+
// t.LRCID (uint64) (uint64)
1151
+
case "lrcID":
1152
+
1153
+
{
1154
+
1155
+
maj, extra, err = cr.ReadHeader()
1156
+
if err != nil {
1157
+
return err
1158
+
}
1159
+
if maj != cbg.MajUnsignedInt {
1160
+
return fmt.Errorf("wrong type for uint64 field")
1161
+
}
1162
+
t.LRCID = uint64(extra)
1163
+
1164
+
}
1165
+
// t.StartedAt (string) (string)
1166
+
case "startedAt":
1167
+
1168
+
{
1169
+
b, err := cr.ReadByte()
1170
+
if err != nil {
1171
+
return err
1172
+
}
1173
+
if b != cbg.CborNull[0] {
1174
+
if err := cr.UnreadByte(); err != nil {
1175
+
return err
1176
+
}
1177
+
1178
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
1179
+
if err != nil {
1180
+
return err
1181
+
}
1182
+
1183
+
t.StartedAt = (*string)(&sval)
1184
+
}
1185
+
}
1186
+
// t.ChannelURI (string) (string)
1187
+
case "channelURI":
1188
+
1189
+
{
1190
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
1191
+
if err != nil {
1192
+
return err
1193
+
}
1194
+
1195
+
t.ChannelURI = string(sval)
1196
+
}
1197
+
1198
+
default:
1199
+
// Field doesn't exist on this type, so ignore it
1200
+
if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
1201
+
return err
1202
+
}
1203
+
}
1204
+
}
1205
+
1206
+
return nil
1207
+
}
+71
lex/types.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
···
1
+
package lex
2
+
3
+
import (
4
+
"github.com/bluesky-social/indigo/lex/util"
5
+
)
6
+
7
+
func init() {
8
+
util.RegisterType("org.xcvr.actor.profile", &ProfileRecord{})
9
+
util.RegisterType("org.xcvr.feed.channel", &ChannelRecord{})
10
+
util.RegisterType("org.xcvr.lrc.message", &MessageRecord{})
11
+
util.RegisterType("org.xcvr.lrc.signet", &SignetRecord{})
12
+
}
13
+
14
+
type ProfileRecord struct {
15
+
LexiconTypeID string `json:"$type,const=org.xcvr.actor.profile" cborgen:"$type,const=org.xcvr.actor.profile"`
16
+
DisplayName *string `json:"displayName,omitempty" cborgen:"displayName,omitempty"`
17
+
DefaultNick *string `json:"defaultNick,omitempty" cborgen:"defaultNick,omitempty"`
18
+
Status *string `json:"status,omitempty" cborgen:"status,omitempty"`
19
+
Avatar *util.LexBlob `json:"avatar,omitempty" cborgen:"avatar,omitempty"`
20
+
Color *uint64 `json:"color,omitempty" cborgen:"color,omitempty"`
21
+
}
22
+
23
+
type ChannelRecord struct {
24
+
LexiconTypeID string `json:"$type,const=org.xcvr.feed.channel" cborgen:"$type,const=org.xcvr.feed.channel"`
25
+
Title string `json:"title" cborgen:"title"`
26
+
Topic *string `json:"topic,omitempty" cborgen:"topic,omitempty"`
27
+
CreatedAt string `json:"createdAt" cborgen:"createdAt"`
28
+
Host string `json:"host" cborgen:"host"`
29
+
}
30
+
31
+
type MessageRecord struct {
32
+
LexiconTypeID string `json:"$type,const=org.xcvr.lrc.message" cborgen:"$type,const=org.xcvr.lrc.message"`
33
+
SignetURI string `json:"signetURI" cborgen:"signetURI"`
34
+
Body string `json:"body" cborgen:"body"`
35
+
Nick *string `json:"nick,omitempty" cborgen:"nick,omitempty"`
36
+
Color *uint64 `json:"color,omitempty" cborgen:"color,omitempty"`
37
+
PostedAt string `json:"postedAt" cborgen:"postedAt"`
38
+
}
39
+
40
+
type SignetRecord struct {
41
+
LexiconTypeID string `json:"$type,const=org.xcvr.lrc.signet" cborgen:"$type,const=org.xcvr.lrc.signet"`
42
+
ChannelURI string `json:"channelURI" cborgen:"channelURI"`
43
+
LRCID uint64 `json:"lrcID" cborgen:"lrcID"`
44
+
AuthorHandle string `json:"authorHandle" cborgen:"authorHandle"`
45
+
StartedAt *string `json:"startedAt,omitempty" cborgen:"startedAt,omitempty"`
46
+
}
47
+
48
+
type MediaRecord struct {
49
+
LexiconTypeID string `json:"$type,const=org.xcvr.lrc.media" cborgen:"$type,const=org.xcvr.lrc.media"`
50
+
SignetURI string `json:"signetURI" cborgen:"signetURI"`
51
+
Media Media `json:"media" cborgen:"media"`
52
+
Nick *string `json:"nick,omitempty" cborgen:"nick,omitempty"`
53
+
Color *uint64 `json:"color,omitempty" cborgen:"color,omitempty"`
54
+
PostedAt string `json:"postedAt" cborgen:"postedAt"`
55
+
}
56
+
57
+
type Media struct {
58
+
Image *Image
59
+
}
60
+
61
+
type Image struct {
62
+
LexiconTypeID string `json:"$type,const=org.xcvr.lrc.image" cborgen:"$type,const=org.xcvr.lrc.image"`
63
+
Alt string `json:"alt" cborgen:"alt"`
64
+
AspectRatio *AspectRatio `json:"aspectRatio,omitempty" cborgen:"aspectRatio,omitempty"`
65
+
Image *util.BlobSchema `json:"image,omitempty" cborgen:"image,omitempty"`
66
+
}
67
+
68
+
type AspectRatio struct {
69
+
Height int64 `json:"height" cborgen:"height"`
70
+
Width int64 `json:"width" cborgen:"width"`
71
+
}
+598
-34
main.go
···
8
"io"
9
"net/http"
10
"os"
0
11
"strings"
12
"time"
13
"unicode/utf16"
14
0
0
0
0
0
15
"github.com/charmbracelet/bubbles/list"
0
16
"github.com/charmbracelet/bubbles/viewport"
17
tea "github.com/charmbracelet/bubbletea"
18
"github.com/charmbracelet/lipgloss"
19
"github.com/gorilla/websocket"
20
"github.com/rachel-mp4/lrcproto/gen/go"
0
21
"google.golang.org/protobuf/proto"
22
)
23
···
60
width int
61
height int
62
error *error
63
-
command *string
0
0
64
channels *[]Channel
65
list *list.Model
66
curchannel *Channel
67
wsurl *string
68
lrcconn *websocket.Conn
0
0
69
cancel func()
70
vp *viewport.Model
71
msgs map[uint32]*Message
0
72
renders []*string
73
topic *string
74
color *uint32
75
nick *string
76
handle *string
0
0
77
}
78
79
type Message struct {
···
140
var desc string
141
var uri string
142
var host string
0
0
143
if i, ok := item.(ChannelItem); ok {
144
title = i.Title()
145
desc = i.Description()
146
-
host = subduedStyle.Render(fmt.Sprintf("(hosted by %s)", i.Host()))
0
147
if desc == "" {
148
desc = subduedStyle.Render("no provided description")
149
}
150
uri = i.URI()
0
151
} else {
152
return
153
}
154
if index == m.Index() {
155
-
greenStyle := lipgloss.NewStyle().Foreground(Green)
156
-
title = fmt.Sprintf("│%s %s", greenStyle.Render(title), host)
157
desc = fmt.Sprintf("│%s", desc)
158
uri = fmt.Sprintf("└%s", strings.Repeat("─", m.Width()-1))
159
} else {
160
s := lipgloss.NewStyle()
161
s = s.Foreground(subduedColor)
162
uri = s.Render(uri)
0
163
}
164
fmt.Fprintf(w, "%s %s\n%s\n%s", title, host, desc, uri)
165
}
166
167
func initialModel() model {
0
0
0
0
168
return model{
169
state: Splash,
170
mode: Normal,
0
171
width: 30,
172
height: 20,
0
0
173
}
174
}
175
func (m model) Init() tea.Cmd {
···
213
214
type errMsg struct{ err error }
215
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
216
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
217
switch msg := msg.(type) {
218
case errMsg:
219
m.state = Error
220
m.error = &msg.err
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
221
222
case tea.WindowSizeMsg:
223
m.height = msg.Height
224
m.width = msg.Width
0
0
0
0
0
0
0
0
0
0
0
0
0
0
225
226
case tea.KeyMsg:
227
switch msg.String() {
···
257
m.error = &err
258
return m, nil
259
}
0
260
switch msg := msg.e.Msg.(type) {
261
case *lrcpb.Event_Ping:
262
return m, nil
···
269
m.error = &err
270
return m, nil
271
}
0
0
0
272
m.vp.SetContent(JoinDeref(m.renders, ""))
273
return m, nil
274
case *lrcpb.Event_Pub:
···
310
}
311
return m, nil
312
case *lrcpb.Event_Editbatch:
0
0
0
0
0
0
0
0
0
0
313
return m, nil
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
314
0
0
0
0
0
315
}
0
316
}
317
-
vp, cmd := m.vp.Update(msg)
318
-
m.vp = &vp
319
-
return m, cmd
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
320
}
321
322
// i think that the type of renders is a bit awkward, but i want deletemessage + friends to just modify the rendered
···
372
result = append(result, baseUTF16Units[end:]...)
373
resultRunes := utf16.Decode(result)
374
return string(resultRunes)
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
375
}
376
377
func insertMessage(msg *lrcpb.Insert, msgmap map[uint32]*Message, renders *[]*string, width int) error {
···
474
return
475
}
476
stylem := lipgloss.NewStyle().Width(width).Align(lipgloss.Left)
477
-
styleh := stylem.Foreground(Green)
478
if m.active {
479
styleh = styleh.Reverse(true)
480
stylem = styleh
481
}
482
-
var nick string
483
-
if m.nick != nil {
484
-
nick = *m.nick
485
-
}
486
-
var handle string
487
-
if m.handle != nil && *m.handle != "" {
488
-
handle = fmt.Sprintf("@%s", *m.handle)
489
-
}
490
-
header := styleh.Render(fmt.Sprintf("%s%s", nick, handle))
491
body := stylem.Render(m.text)
492
*m.rendered = fmt.Sprintf("%s\n%s\n", header, body)
493
}
···
498
m.state = Connected
499
m.cancel = msg.cancel
500
m.msgs = make(map[uint32]*Message)
501
-
vp := viewport.New(m.width, m.height-1)
502
m.vp = &vp
503
-
go startLRCHandlers(msg.conn)
0
0
0
0
0
0
0
0
0
0
504
return m, nil
505
}
506
return m, nil
507
}
508
509
-
func startLRCHandlers(conn *websocket.Conn) {
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
510
if conn == nil {
511
send(errMsg{errors.New("provided nil conn")})
512
return
513
}
514
-
nick := "wanderer"
515
-
evt := &lrcpb.Event{Msg: &lrcpb.Event_Set{Set: &lrcpb.Set{Nick: &nick}}}
516
data, err := proto.Marshal(evt)
517
if err != nil {
518
send(errMsg{errors.New("failed to marshal: " + err.Error())})
519
return
520
}
0
521
522
-
evt = &lrcpb.Event{Msg: &lrcpb.Event_Get{Get: &lrcpb.Get{Topic: &nick}}}
0
523
data, err = proto.Marshal(evt)
524
if err != nil {
525
send(errMsg{errors.New("failed to marshal: " + err.Error())})
···
527
}
528
conn.WriteMessage(websocket.BinaryMessage, data)
529
go listenToConn(conn)
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
530
}
531
532
func listenToConn(conn *websocket.Conn) {
···
568
if err != nil {
569
return errMsg{err}
570
}
571
-
return connMsg{conn, cancel}
0
0
0
0
0
0
572
}
573
}
574
575
type connMsg struct {
576
-
conn *websocket.Conn
577
-
cancel func()
0
578
}
579
580
const (
···
707
}
708
remainingspace := m.width - len(address) - len(topic)
709
var footertext string
710
-
if remainingspace < 1 {
711
-
footertext = address
0
0
712
} else {
713
footertext = fmt.Sprintf("%s%s%s", address, strings.Repeat(" ", remainingspace), topic)
714
}
715
insert := m.mode == Insert
716
-
footerstyle := lipgloss.NewStyle().Foreground(Green).Reverse(insert)
0
0
0
717
footer := footerstyle.Render(footertext)
718
-
return fmt.Sprintf("%s\n%s", vpt, footer)
0
0
0
0
719
}
0
720
func (m model) connectingView() string {
721
blip := m.wsurl
722
if blip == nil {
···
731
732
func (m model) splashView() string {
733
style := lipgloss.NewStyle().Foreground(Green)
734
-
part1 := "\n %%%%%%% "
0
0
0
0
735
text1 := "tty!xcvr\n"
736
part2 := ` %%%%%%%%%% %%% % % %%%%%%%%
737
%%%%%%%%%%%%%%%%% %%%% %%%%%%%%%%%%%%%%%%
···
753
press a key
754
to start!
755
`
756
-
s := fmt.Sprintf("%s%s%s%s%s%s%s%s%s", style.Render(part1), text1, style.Render(part2), style.Render(part25), text2, style.Render(part3), text3, style.Render(part4), text4)
757
-
758
-
return s
759
}
760
761
var send func(msg tea.Msg)
···
899
}
900
return b.String()
901
}
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
···
8
"io"
9
"net/http"
10
"os"
11
+
"strconv"
12
"strings"
13
"time"
14
"unicode/utf16"
15
16
+
"github.com/bluesky-social/indigo/api/atproto"
17
+
"github.com/bluesky-social/indigo/atproto/client"
18
+
"github.com/bluesky-social/indigo/atproto/identity"
19
+
"github.com/bluesky-social/indigo/atproto/syntax"
20
+
"github.com/bluesky-social/indigo/lex/util"
21
"github.com/charmbracelet/bubbles/list"
22
+
"github.com/charmbracelet/bubbles/textinput"
23
"github.com/charmbracelet/bubbles/viewport"
24
tea "github.com/charmbracelet/bubbletea"
25
"github.com/charmbracelet/lipgloss"
26
"github.com/gorilla/websocket"
27
"github.com/rachel-mp4/lrcproto/gen/go"
28
+
"github.com/rachel-mp4/ttyxcvr/lex"
29
"google.golang.org/protobuf/proto"
30
)
31
···
68
width int
69
height int
70
error *error
71
+
prompt textinput.Model
72
+
draft *textinput.Model
73
+
sentmsg *string
74
channels *[]Channel
75
list *list.Model
76
curchannel *Channel
77
wsurl *string
78
lrcconn *websocket.Conn
79
+
lexconn *websocket.Conn
80
+
evtchan chan []byte
81
cancel func()
82
vp *viewport.Model
83
msgs map[uint32]*Message
84
+
myid *uint32
85
renders []*string
86
topic *string
87
color *uint32
88
nick *string
89
handle *string
90
+
signeturi *string
91
+
xrpc *PasswordClient
92
}
93
94
type Message struct {
···
155
var desc string
156
var uri string
157
var host string
158
+
var color *uint32
159
+
var author string
160
if i, ok := item.(ChannelItem); ok {
161
title = i.Title()
162
desc = i.Description()
163
+
author = fmt.Sprintf("(%s)", renderName(i.channel.Creator.DisplayName, i.channel.Creator.Handle))
164
+
host = subduedStyle.Render(fmt.Sprintf("(hosted on %s)", i.Host()))
165
if desc == "" {
166
desc = subduedStyle.Render("no provided description")
167
}
168
uri = i.URI()
169
+
color = i.channel.Creator.Color
170
} else {
171
return
172
}
173
if index == m.Index() {
174
+
greenStyle := lipgloss.NewStyle().Foreground(ColorFromInt(color))
175
+
title = fmt.Sprintf("│%s %s", greenStyle.Render(title), author)
176
desc = fmt.Sprintf("│%s", desc)
177
uri = fmt.Sprintf("└%s", strings.Repeat("─", m.Width()-1))
178
} else {
179
s := lipgloss.NewStyle()
180
s = s.Foreground(subduedColor)
181
uri = s.Render(uri)
182
+
host = subduedStyle.Render(author)
183
}
184
fmt.Fprintf(w, "%s %s\n%s\n%s", title, host, desc, uri)
185
}
186
187
func initialModel() model {
188
+
prompt := textinput.New()
189
+
prompt.Prompt = ":"
190
+
nick := "wanderer"
191
+
color := uint32(33096)
192
return model{
193
state: Splash,
194
mode: Normal,
195
+
prompt: prompt,
196
width: 30,
197
height: 20,
198
+
nick: &nick,
199
+
color: &color,
200
}
201
}
202
func (m model) Init() tea.Cmd {
···
240
241
type errMsg struct{ err error }
242
243
+
func login(handle string, secret string) tea.Cmd {
244
+
return func() tea.Msg {
245
+
hdl, err := syntax.ParseHandle(handle)
246
+
if err != nil {
247
+
err = errors.New("handle failed to parse: " + err.Error())
248
+
return errMsg{err}
249
+
}
250
+
id, err := identity.DefaultDirectory().LookupHandle(context.Background(), hdl)
251
+
if err != nil {
252
+
err = errors.New("handle failed to loopup: " + err.Error())
253
+
return errMsg{err}
254
+
}
255
+
xrpc := NewPasswordClient(id.DID.String(), id.PDSEndpoint())
256
+
err = xrpc.CreateSession(context.Background(), handle, secret)
257
+
if err != nil {
258
+
return errMsg{err}
259
+
}
260
+
return loggedInMsg{xrpc}
261
+
}
262
+
}
263
+
264
+
type loggedInMsg struct {
265
+
xrpc *PasswordClient
266
+
}
267
+
268
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
269
switch msg := msg.(type) {
270
case errMsg:
271
m.state = Error
272
m.error = &msg.err
273
+
return m, nil
274
+
case svMsg:
275
+
if m.myid != nil && msg.signetView.LrcId == *m.myid {
276
+
m.signeturi = &msg.signetView.URI
277
+
return m, nil
278
+
}
279
+
280
+
case loginMsg:
281
+
if len(msg.value) == 2 {
282
+
return m, login(msg.value[0], msg.value[1])
283
+
}
284
+
case loggedInMsg:
285
+
m.xrpc = msg.xrpc
286
+
return m, nil
287
+
288
+
case setMsg:
289
+
key, val, found := strings.Cut(msg.value, "=")
290
+
if !found {
291
+
return m, nil
292
+
}
293
+
switch key {
294
+
case "color", "c":
295
+
i, err := strconv.Atoi(val)
296
+
if err != nil {
297
+
return m, nil
298
+
}
299
+
b := uint32(i)
300
+
m.color = &b
301
+
if m.draft != nil {
302
+
m.draft.PromptStyle = lipgloss.NewStyle().Foreground(ColorFromInt(&b))
303
+
}
304
+
err = sendSet(m.evtchan, m.nick, m.handle, m.color)
305
+
if err != nil {
306
+
send(errMsg{err})
307
+
}
308
+
return m, nil
309
+
case "nick", "name", "n":
310
+
m.nick = &val
311
+
if m.draft != nil {
312
+
m.draft.Prompt = renderName(m.nick, m.handle) + " "
313
+
}
314
+
err := sendSet(m.evtchan, m.nick, m.handle, m.color)
315
+
if err != nil {
316
+
send(errMsg{err})
317
+
}
318
+
return m, nil
319
+
case "handle", "h", "at", "@":
320
+
m.handle = &val
321
+
if m.draft != nil {
322
+
m.draft.Prompt = renderName(m.nick, m.handle) + " "
323
+
}
324
+
err := sendSet(m.evtchan, m.nick, m.handle, m.color)
325
+
if err != nil {
326
+
send(errMsg{err})
327
+
}
328
+
return m, nil
329
+
}
330
331
case tea.WindowSizeMsg:
332
m.height = msg.Height
333
m.width = msg.Width
334
+
if m.vp != nil {
335
+
m.vp.Width = msg.Width
336
+
m.vp.Height = msg.Height - 2
337
+
}
338
+
if m.renders != nil {
339
+
for _, message := range m.msgs {
340
+
message.renderMessage(msg.Width)
341
+
}
342
+
m.vp.SetContent(JoinDeref(m.renders, ""))
343
+
}
344
+
if m.list != nil {
345
+
m.list.SetSize(msg.Width, msg.Height)
346
+
}
347
+
return m, nil
348
349
case tea.KeyMsg:
350
switch msg.String() {
···
380
m.error = &err
381
return m, nil
382
}
383
+
id := msg.e.Id
384
switch msg := msg.e.Msg.(type) {
385
case *lrcpb.Event_Ping:
386
return m, nil
···
393
m.error = &err
394
return m, nil
395
}
396
+
if msg.Init.Echoed != nil && *msg.Init.Echoed {
397
+
m.myid = msg.Init.Id
398
+
}
399
m.vp.SetContent(JoinDeref(m.renders, ""))
400
return m, nil
401
case *lrcpb.Event_Pub:
···
437
}
438
return m, nil
439
case *lrcpb.Event_Editbatch:
440
+
if id == nil {
441
+
return m, nil
442
+
}
443
+
err := editMessage(*id, msg.Editbatch.Edits, m.msgs, &m.renders, m.width)
444
+
if err != nil {
445
+
m.state = Error
446
+
m.error = &err
447
+
return m, nil
448
+
}
449
+
m.vp.SetContent(JoinDeref(m.renders, ""))
450
return m, nil
451
+
}
452
+
case tea.KeyMsg:
453
+
switch m.mode {
454
+
case Normal:
455
+
switch msg.String() {
456
+
case "i", "a":
457
+
m.mode = Insert
458
+
return m, m.draft.Focus()
459
+
case ":":
460
+
m.mode = Command
461
+
return m, m.prompt.Focus()
462
+
}
463
+
case Insert:
464
+
switch msg.String() {
465
+
case "esc":
466
+
m.mode = Normal
467
+
m.draft.Blur()
468
+
return m, nil
469
+
case "enter":
470
+
if m.sentmsg != nil {
471
+
if m.xrpc != nil && m.signeturi != nil {
472
+
var color64 *uint64
473
+
if m.color != nil {
474
+
c64 := uint64(*m.color)
475
+
color64 = &c64
476
+
}
477
+
lmr := lex.MessageRecord{
478
+
SignetURI: *m.signeturi,
479
+
Body: *m.sentmsg,
480
+
Nick: m.nick,
481
+
Color: color64,
482
+
PostedAt: syntax.DatetimeNow().String(),
483
+
}
484
+
m.draft.SetValue("")
485
+
m.sentmsg = nil
486
+
m.myid = nil
487
+
m.signeturi = nil
488
+
return m, tea.Batch(sendPub(m.lrcconn), createMSGCmd(m.xrpc, &lmr))
489
+
}
490
+
m.draft.SetValue("")
491
+
m.sentmsg = nil
492
+
return m, sendPub(m.lrcconn)
493
+
}
494
+
return m, nil
495
+
}
496
+
case Command:
497
+
switch msg.String() {
498
+
case "esc":
499
+
m.mode = Normal
500
+
m.prompt.Blur()
501
+
m.prompt.SetValue("")
502
+
return m, nil
503
+
case "enter":
504
+
m.mode = Normal
505
+
m.prompt.Blur()
506
+
v := m.prompt.Value()
507
+
m.prompt.SetValue("")
508
+
return m, evaluateCommand(v)
509
+
default:
510
+
}
511
+
}
512
+
}
513
+
switch m.mode {
514
+
case Normal:
515
+
vp, cmd := m.vp.Update(msg)
516
+
m.vp = &vp
517
+
return m, cmd
518
+
case Command:
519
+
prompt, cmd := m.prompt.Update(msg)
520
+
m.prompt = prompt
521
+
return m, cmd
522
+
case Insert:
523
+
draft, cmd := m.draft.Update(msg)
524
+
if m.sentmsg == nil && draft.Value() != "" {
525
+
nv := draft.Value()
526
+
m.sentmsg = &nv
527
+
m.draft = &draft
528
+
return m, tea.Batch(cmd, sendInsert(m.lrcconn, nv, 0, true))
529
+
}
530
+
if m.sentmsg != nil && *m.sentmsg != draft.Value() {
531
+
draftutf16 := utf16.Encode([]rune(draft.Value()))
532
+
sentutf16 := utf16.Encode([]rune(*m.sentmsg))
533
+
edits := Diff(sentutf16, draftutf16)
534
+
m.draft = &draft
535
+
sentmsg := draft.Value()
536
+
m.sentmsg = &sentmsg
537
+
return m, tea.Batch(cmd, sendEditBatch(m.evtchan, edits))
538
+
}
539
+
m.draft = &draft
540
+
return m, cmd
541
+
}
542
+
return m, nil
543
+
}
544
545
+
func createMSGCmd(xrpc *PasswordClient, lmr *lex.MessageRecord) tea.Cmd {
546
+
return func() tea.Msg {
547
+
_, _, err := xrpc.CreateXCVRMessage(lmr, context.Background())
548
+
if err != nil {
549
+
return errMsg{err}
550
}
551
+
return nil
552
}
553
+
}
554
+
555
+
func sendEditBatch(datachan chan []byte, edits []Edit) tea.Cmd {
556
+
return func() tea.Msg {
557
+
idx := 0
558
+
batch := make([]*lrcpb.Edit, 0)
559
+
for _, edit := range edits {
560
+
switch edit.EditType {
561
+
case EditDel:
562
+
idx2 := idx + len(edit.Utf16Text)
563
+
evt := makeDelete(uint32(idx), uint32(idx2))
564
+
edit := lrcpb.Edit{Edit: &lrcpb.Edit_Delete{Delete: evt.GetDelete()}}
565
+
batch = append(batch, &edit)
566
+
case EditKeep:
567
+
idx = idx + len(edit.Utf16Text)
568
+
case EditAdd:
569
+
evt := makeInsert(string(utf16.Decode(edit.Utf16Text)), uint32(idx))
570
+
idx = idx + len(edit.Utf16Text)
571
+
edit := lrcpb.Edit{Edit: &lrcpb.Edit_Insert{Insert: evt.GetInsert()}}
572
+
batch = append(batch, &edit)
573
+
}
574
+
}
575
+
evt := lrcpb.Event{Msg: &lrcpb.Event_Editbatch{Editbatch: &lrcpb.EditBatch{Edits: batch}}}
576
+
data, err := proto.Marshal(&evt)
577
+
if err != nil {
578
+
return errMsg{err}
579
+
}
580
+
datachan <- data
581
+
return nil
582
+
}
583
+
}
584
+
585
+
func sendPub(conn *websocket.Conn) tea.Cmd {
586
+
return func() tea.Msg {
587
+
evt := &lrcpb.Event{Msg: &lrcpb.Event_Pub{Pub: &lrcpb.Pub{}}}
588
+
data, err := proto.Marshal(evt)
589
+
if err != nil {
590
+
return errMsg{err}
591
+
}
592
+
err = conn.WriteMessage(websocket.BinaryMessage, data)
593
+
if err != nil {
594
+
return errMsg{err}
595
+
}
596
+
return nil
597
+
}
598
+
}
599
+
600
+
func makeDelete(start uint32, end uint32) *lrcpb.Event {
601
+
evt := &lrcpb.Event{Msg: &lrcpb.Event_Delete{Delete: &lrcpb.Delete{Utf16Start: start, Utf16End: end}}}
602
+
return evt
603
+
}
604
+
605
+
func makeInsert(body string, idx uint32) *lrcpb.Event {
606
+
evt := &lrcpb.Event{Msg: &lrcpb.Event_Insert{Insert: &lrcpb.Insert{Body: body, Utf16Index: idx}}}
607
+
return evt
608
+
}
609
+
610
+
func sendInsert(conn *websocket.Conn, body string, utf16idx uint32, init bool) tea.Cmd {
611
+
return func() tea.Msg {
612
+
if init {
613
+
evt := &lrcpb.Event{Msg: &lrcpb.Event_Init{Init: &lrcpb.Init{}}}
614
+
data, err := proto.Marshal(evt)
615
+
if err != nil {
616
+
return errMsg{err}
617
+
}
618
+
if conn == nil {
619
+
return nil
620
+
}
621
+
err = conn.WriteMessage(websocket.BinaryMessage, data)
622
+
if err != nil {
623
+
return errMsg{err}
624
+
}
625
+
}
626
+
evt := &lrcpb.Event{Msg: &lrcpb.Event_Insert{Insert: &lrcpb.Insert{Body: body, Utf16Index: utf16idx}}}
627
+
data, err := proto.Marshal(evt)
628
+
if err != nil {
629
+
return errMsg{err}
630
+
}
631
+
err = conn.WriteMessage(websocket.BinaryMessage, data)
632
+
if err != nil {
633
+
return errMsg{err}
634
+
}
635
+
return nil
636
+
}
637
+
}
638
+
639
+
func evaluateCommand(command string) tea.Cmd {
640
+
return func() tea.Msg {
641
+
parts := strings.Split(command, " ")
642
+
if parts == nil {
643
+
return nil
644
+
}
645
+
switch parts[0] {
646
+
case "q":
647
+
return tea.QuitMsg{}
648
+
case "se", "set":
649
+
if len(parts) != 1 {
650
+
return setMsg{parts[1]}
651
+
}
652
+
case "resize":
653
+
return tea.WindowSize()
654
+
case "login":
655
+
if len(parts) != 1 {
656
+
return loginMsg{parts[1:]}
657
+
}
658
+
}
659
+
return nil
660
+
}
661
+
}
662
+
663
+
type loginMsg struct {
664
+
value []string
665
+
}
666
+
667
+
type setMsg struct {
668
+
value string
669
}
670
671
// i think that the type of renders is a bit awkward, but i want deletemessage + friends to just modify the rendered
···
721
result = append(result, baseUTF16Units[end:]...)
722
resultRunes := utf16.Decode(result)
723
return string(resultRunes)
724
+
}
725
+
726
+
func editMessage(id uint32, edits []*lrcpb.Edit, msgmap map[uint32]*Message, renders *[]*string, width int) error {
727
+
for _, edit := range edits {
728
+
switch e := edit.Edit.(type) {
729
+
case *lrcpb.Edit_Insert:
730
+
ins := e.Insert
731
+
ins.Id = &id
732
+
err := insertMessage(ins, msgmap, renders, width)
733
+
if err != nil {
734
+
return err
735
+
}
736
+
case *lrcpb.Edit_Delete:
737
+
del := e.Delete
738
+
del.Id = &id
739
+
err := deleteMessage(del, msgmap, renders, width)
740
+
if err != nil {
741
+
return err
742
+
}
743
+
}
744
+
}
745
+
return nil
746
}
747
748
func insertMessage(msg *lrcpb.Insert, msgmap map[uint32]*Message, renders *[]*string, width int) error {
···
845
return
846
}
847
stylem := lipgloss.NewStyle().Width(width).Align(lipgloss.Left)
848
+
styleh := stylem.Foreground(ColorFromInt(m.color))
849
if m.active {
850
styleh = styleh.Reverse(true)
851
stylem = styleh
852
}
853
+
header := styleh.Render(renderName(m.nick, m.handle))
0
0
0
0
0
0
0
0
854
body := stylem.Render(m.text)
855
*m.rendered = fmt.Sprintf("%s\n%s\n", header, body)
856
}
···
861
m.state = Connected
862
m.cancel = msg.cancel
863
m.msgs = make(map[uint32]*Message)
864
+
vp := viewport.New(m.width, m.height-2)
865
m.vp = &vp
866
+
draft := textinput.New()
867
+
draft.Prompt = renderName(m.nick, m.handle) + " "
868
+
draft.PromptStyle = lipgloss.NewStyle().Foreground(ColorFromInt(m.color))
869
+
draft.Placeholder = "press i to start typing"
870
+
draft.Width = m.width
871
+
m.draft = &draft
872
+
go startLRCHandlers(msg.conn, msg.lexconn, m.nick, m.handle, m.color)
873
+
m.lrcconn = msg.conn
874
+
m.lexconn = msg.lexconn
875
+
m.evtchan = make(chan []byte)
876
+
go LRCWriter(m.lrcconn, m.evtchan)
877
return m, nil
878
}
879
return m, nil
880
}
881
882
+
func LRCWriter(conn *websocket.Conn, datachan chan []byte) {
883
+
for data := range datachan {
884
+
err := conn.WriteMessage(websocket.BinaryMessage, data)
885
+
if err != nil {
886
+
send(errMsg{err})
887
+
return
888
+
}
889
+
}
890
+
}
891
+
892
+
func renderName(nick *string, handle *string) string {
893
+
var n string
894
+
if nick != nil {
895
+
n = *nick
896
+
}
897
+
var h string
898
+
if handle != nil {
899
+
h = fmt.Sprintf("@%s", *handle)
900
+
}
901
+
return fmt.Sprintf("%s%s", n, h)
902
+
}
903
+
904
+
func sendSet(datachan chan []byte, nick *string, handle *string, color *uint32) error {
905
+
evt := &lrcpb.Event{Msg: &lrcpb.Event_Set{Set: &lrcpb.Set{Nick: nick, ExternalID: handle, Color: color}}}
906
+
data, err := proto.Marshal(evt)
907
+
if err != nil {
908
+
return err
909
+
}
910
+
datachan <- data
911
+
return nil
912
+
913
+
}
914
+
915
+
func startLRCHandlers(conn *websocket.Conn, lexconn *websocket.Conn, nick *string, handle *string, color *uint32) {
916
if conn == nil {
917
send(errMsg{errors.New("provided nil conn")})
918
return
919
}
920
+
evt := &lrcpb.Event{Msg: &lrcpb.Event_Set{Set: &lrcpb.Set{Nick: nick, ExternalID: handle, Color: color}}}
0
921
data, err := proto.Marshal(evt)
922
if err != nil {
923
send(errMsg{errors.New("failed to marshal: " + err.Error())})
924
return
925
}
926
+
conn.WriteMessage(websocket.BinaryMessage, data)
927
928
+
bep := "bep"
929
+
evt = &lrcpb.Event{Msg: &lrcpb.Event_Get{Get: &lrcpb.Get{Topic: &bep}}}
930
data, err = proto.Marshal(evt)
931
if err != nil {
932
send(errMsg{errors.New("failed to marshal: " + err.Error())})
···
934
}
935
conn.WriteMessage(websocket.BinaryMessage, data)
936
go listenToConn(conn)
937
+
go listenToLexConn(lexconn)
938
+
}
939
+
940
+
type typedJSON struct {
941
+
Type string `json:"$type"`
942
+
}
943
+
944
+
func listenToLexConn(conn *websocket.Conn) {
945
+
for {
946
+
var rawMsg json.RawMessage
947
+
err := conn.ReadJSON(&rawMsg)
948
+
if err != nil {
949
+
send(errMsg{err})
950
+
return
951
+
}
952
+
var typed typedJSON
953
+
err = json.Unmarshal(rawMsg, &typed)
954
+
if err != nil {
955
+
send(errMsg{err})
956
+
return
957
+
}
958
+
switch typed.Type {
959
+
case "org.xcvr.lrc.defs#signetView":
960
+
var sv SignetView
961
+
err = json.Unmarshal(rawMsg, &sv)
962
+
if err != nil {
963
+
send(errMsg{err})
964
+
return
965
+
}
966
+
send(svMsg{&sv})
967
+
}
968
+
}
969
+
}
970
+
971
+
type svMsg struct {
972
+
signetView *SignetView
973
+
}
974
+
975
+
type SignetView struct {
976
+
Type string `json:"$type,const=org.xcvr.lrc.defs#signetView"`
977
+
URI string `json:"uri"`
978
+
IssuerHandle string `json:"issuerHandle"`
979
+
ChannelURI string `json:"channelURI"`
980
+
LrcId uint32 `json:"lrcID"`
981
+
AuthorHandle string `json:"authorHandle"`
982
+
StartedAt time.Time `json:"startedAt"`
983
}
984
985
func listenToConn(conn *websocket.Conn) {
···
1021
if err != nil {
1022
return errMsg{err}
1023
}
1024
+
1025
+
dialer = websocket.DefaultDialer
1026
+
lexconn, _, err := dialer.DialContext(ctx, fmt.Sprintf("wss://xcvr.org/xrpc/org.xcvr.lrc.subscribeLexStream?uri=%s", m.curchannel.URI), http.Header{})
1027
+
if err != nil {
1028
+
return errMsg{err}
1029
+
}
1030
+
return connMsg{conn, lexconn, cancel}
1031
}
1032
}
1033
1034
type connMsg struct {
1035
+
conn *websocket.Conn
1036
+
lexconn *websocket.Conn
1037
+
cancel func()
1038
}
1039
1040
const (
···
1167
}
1168
remainingspace := m.width - len(address) - len(topic)
1169
var footertext string
1170
+
if m.mode == Command {
1171
+
footertext = m.prompt.View()
1172
+
} else if remainingspace < 1 {
1173
+
footertext = fmt.Sprintf("%s%s", address, strings.Repeat(" ", m.width-len(address)))
1174
} else {
1175
footertext = fmt.Sprintf("%s%s%s", address, strings.Repeat(" ", remainingspace), topic)
1176
}
1177
insert := m.mode == Insert
1178
+
footerstyle := lipgloss.NewStyle().Reverse(insert)
1179
+
if m.mode != Command {
1180
+
footerstyle = footerstyle.Foreground(ColorFromInt(m.color))
1181
+
}
1182
footer := footerstyle.Render(footertext)
1183
+
var draftText string
1184
+
if m.draft != nil {
1185
+
draftText = m.draft.View()
1186
+
}
1187
+
return fmt.Sprintf("%s\n%s\n%s", vpt, draftText, footer)
1188
}
1189
+
1190
func (m model) connectingView() string {
1191
blip := m.wsurl
1192
if blip == nil {
···
1201
1202
func (m model) splashView() string {
1203
style := lipgloss.NewStyle().Foreground(Green)
1204
+
part00 := "\n ⣰⡀ ⢀⣀ ⡇ ⡇⡠ ⣰⡀ ⢀⡀ ⡀⢀ ⢀⡀ ⡀⢀ ⡇"
1205
+
part01 := "\n ⠘⠤ ⠣⠼ ⠣ ⠏⠢ ⠘⠤ ⠣⠜ ⣑⡺ ⠣⠜ ⠣⠼ ⠅"
1206
+
part02 := "\n ⣰⡀ ⡀⣀ ⢀⣀ ⣀⡀ ⢀⣀ ⢀⣀ ⢀⡀ ⠄ ⡀⢀ ⢀⡀ ⡀⣀"
1207
+
part03 := "\n ⠘⠤ ⠏ ⠣⠼ ⠇⠸ ⠭⠕ ⠣⠤ ⠣⠭ ⠇ ⠱⠃ ⠣⠭ ⠏"
1208
+
part1 := "\n\n %%%%%%% "
1209
text1 := "tty!xcvr\n"
1210
part2 := ` %%%%%%%%%% %%% % % %%%%%%%%
1211
%%%%%%%%%%%%%%%%% %%%% %%%%%%%%%%%%%%%%%%
···
1227
press a key
1228
to start!
1229
`
1230
+
s := fmt.Sprintf("\n\n\n\n%s%s%s%s%s%s%s%s%s%s%s%s%s", style.Render(part00), style.Render(part01), style.Render(part02), style.Render(part03), style.Render(part1), text1, style.Render(part2), style.Render(part25), text2, style.Render(part3), text3, style.Render(part4), text4)
1231
+
offset := lipgloss.NewStyle().MarginLeft((m.width - 58) / 2)
1232
+
return offset.Render(s)
1233
}
1234
1235
var send func(msg tea.Msg)
···
1373
}
1374
return b.String()
1375
}
1376
+
1377
+
type PasswordClient struct {
1378
+
xrpc *client.APIClient
1379
+
accessjwt *string
1380
+
refreshjwt *string
1381
+
did *string
1382
+
}
1383
+
1384
+
func NewPasswordClient(did string, host string) *PasswordClient {
1385
+
return &PasswordClient{
1386
+
xrpc: client.NewAPIClient(host),
1387
+
did: &did,
1388
+
}
1389
+
}
1390
+
1391
+
func (c *PasswordClient) CreateSession(ctx context.Context, identity string, secret string) error {
1392
+
input := atproto.ServerCreateSession_Input{
1393
+
Identifier: identity,
1394
+
Password: secret,
1395
+
}
1396
+
var out atproto.ServerCreateSession_Output
1397
+
err := c.xrpc.LexDo(ctx, "POST", "application/json", "com.atproto.server.createSession", nil, input, &out)
1398
+
if err != nil {
1399
+
return errors.New("I couldn't create a session: " + err.Error())
1400
+
}
1401
+
c.accessjwt = &out.AccessJwt
1402
+
c.refreshjwt = &out.RefreshJwt
1403
+
return nil
1404
+
}
1405
+
1406
+
func (c *PasswordClient) RefreshSession(ctx context.Context) error {
1407
+
c.xrpc.Headers.Set("Authorization", fmt.Sprintf("Bearer %s", *c.refreshjwt))
1408
+
var out atproto.ServerRefreshSession_Output
1409
+
err := c.xrpc.LexDo(ctx, "POST", "application/json", "com.atproto.server.refreshSession", nil, nil, &out)
1410
+
if err != nil {
1411
+
return errors.New("failed to refresh session! " + err.Error())
1412
+
}
1413
+
c.accessjwt = &out.AccessJwt
1414
+
c.refreshjwt = &out.RefreshJwt
1415
+
return nil
1416
+
}
1417
+
1418
+
func (c *PasswordClient) CreateXCVRMessage(message *lex.MessageRecord, ctx context.Context) (cid string, uri string, err error) {
1419
+
input := atproto.RepoCreateRecord_Input{
1420
+
Collection: "org.xcvr.lrc.message",
1421
+
Repo: *c.did,
1422
+
Record: &util.LexiconTypeDecoder{Val: message},
1423
+
}
1424
+
return c.createMyRecord(input, ctx)
1425
+
}
1426
+
1427
+
func (c *PasswordClient) createMyRecord(input atproto.RepoCreateRecord_Input, ctx context.Context) (cid string, uri string, err error) {
1428
+
if c.accessjwt == nil {
1429
+
err = errors.New("must create a session first")
1430
+
return
1431
+
}
1432
+
c.xrpc.Headers.Set("Authorization", fmt.Sprintf("Bearer %s", *c.accessjwt))
1433
+
var out atproto.RepoCreateRecord_Output
1434
+
err = c.xrpc.LexDo(ctx, "POST", "application/json", "com.atproto.repo.createRecord", nil, input, &out)
1435
+
if err != nil {
1436
+
err1 := err.Error()
1437
+
err = c.RefreshSession(ctx)
1438
+
if err != nil {
1439
+
err = errors.New(fmt.Sprintf("failed to refresh session while creating %s! first %s then %s", input.Collection, err1, err.Error()))
1440
+
return
1441
+
}
1442
+
c.xrpc.Headers.Set("Authorization", fmt.Sprintf("Bearer %s", *c.accessjwt))
1443
+
out = atproto.RepoCreateRecord_Output{}
1444
+
err = c.xrpc.LexDo(ctx, "POST", "application/json", "com.atproto.repo.createRecord", nil, input, &out)
1445
+
if err != nil {
1446
+
err = errors.New(fmt.Sprintf("not good, failed to create %s after failing then refreshing session! first %s then %s", input.Collection, err1, err.Error()))
1447
+
return
1448
+
}
1449
+
cid = out.Cid
1450
+
uri = out.Uri
1451
+
return
1452
+
}
1453
+
cid = out.Cid
1454
+
uri = out.Uri
1455
+
return
1456
+
}
1457
+
1458
+
func ColorFromInt(c *uint32) lipgloss.Color {
1459
+
if c == nil {
1460
+
return Green
1461
+
}
1462
+
ui := *c
1463
+
guess := fmt.Sprintf("#%06x", ui)
1464
+
return lipgloss.Color(guess[0:7])
1465
+
}