+4
-3
lexicons/org/xcvr/notes.lex
+4
-3
lexicons/org/xcvr/notes.lex
···
54
54
title: string, bytes<=640, chars<=64
55
55
topic?: string, bytes<=2560, chars<=256
56
56
createdAt: string
57
-
host: handle
57
+
host: did
58
58
59
59
sub: record
60
60
channelUri: uri
61
61
62
62
channelView?: def
63
63
uri: uri
64
-
host: handle
64
+
host: did
65
65
creator: org.xcvr.actor.profileView
66
66
title: string, bytes<=640, chars<=64
67
67
topic?: string, bytes<=2560, chars<=256
···
88
88
signet: record
89
89
channelURI: uri
90
90
lrcID: int, [0 4294967295]
91
-
author: string
91
+
author: did
92
+
authorHandle?: string
92
93
startedAt?: date
93
94
94
95
media: record
+1
migrations/008_updatexcvrdid.down.sql
+1
migrations/008_updatexcvrdid.down.sql
···
1
+
UPDATE did_handles SET did = 'did:plc:mqt7hthieqzpa3mwqwggbqei' WHERE handle = 'xcvr.org';
+1
migrations/008_updatexcvrdid.up.sql
+1
migrations/008_updatexcvrdid.up.sql
···
1
+
UPDATE did_handles SET did = 'did:web:xcvr.org' WHERE handle = 'xcvr.org';
+2
-2
server/go.mod
+2
-2
server/go.mod
···
10
10
github.com/ipfs/go-cid v0.4.1
11
11
github.com/jackc/pgx/v5 v5.7.4
12
12
github.com/joho/godotenv v1.5.1
13
-
github.com/rachel-mp4/lrcd v0.1.1
14
-
github.com/rachel-mp4/lrcproto v1.2.0
13
+
github.com/rachel-mp4/lrcd v0.2.3
14
+
github.com/rachel-mp4/lrcproto v1.2.1
15
15
github.com/rivo/uniseg v0.4.7
16
16
github.com/whyrusleeping/cbor-gen v0.3.1
17
17
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
+6
-14
server/go.sum
+6
-14
server/go.sum
···
24
24
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
25
25
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
26
26
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
27
-
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
28
-
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
27
+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
28
+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
29
29
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
30
30
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
31
31
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
···
117
117
github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ=
118
118
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
119
119
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
120
-
github.com/rachel-mp4/lrcd v0.0.1 h1:9d5if0HJ/+TLKdupd7Zu9dISA5fF3QRtI/yr+gYVqXM=
121
-
github.com/rachel-mp4/lrcd v0.0.1/go.mod h1:aWUVglSyrLf2RGpQdqTucX498b434yWBFJkD6Yzr0OE=
122
-
github.com/rachel-mp4/lrcd v0.1.0 h1:iW3ux8otqo+9tYpP2Bsxu5VgbhP324Mjy0vOBf3M39Q=
123
-
github.com/rachel-mp4/lrcd v0.1.0/go.mod h1:CyBPWmy94oQ0sTOj24VJjxWoZ9zSnqCKQ/qlR+vhtVE=
124
-
github.com/rachel-mp4/lrcd v0.1.1 h1:2AXK61+pnL71ZqINLnxNfKqX/F0hUw+REFbBFZOjJcY=
125
-
github.com/rachel-mp4/lrcd v0.1.1/go.mod h1:CyBPWmy94oQ0sTOj24VJjxWoZ9zSnqCKQ/qlR+vhtVE=
126
-
github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c h1:t33xVlfSwvB80nj1jroRXUaq/RTgjWwD4l7p/ISatUQ=
127
-
github.com/rachel-mp4/lrcproto v0.0.0-20250905154858-2ddb78e31d0c/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw=
128
-
github.com/rachel-mp4/lrcproto v1.2.0 h1:nZI80WQKO6yKgX0O5H6OO1cM/tiJqugs0p52KCoIDOw=
129
-
github.com/rachel-mp4/lrcproto v1.2.0/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw=
120
+
github.com/rachel-mp4/lrcd v0.2.3 h1:HT3UjFn2ZK2zpFkS8U7KU1+I9kMA/oBF2FVWd7x0TkM=
121
+
github.com/rachel-mp4/lrcd v0.2.3/go.mod h1:CyBPWmy94oQ0sTOj24VJjxWoZ9zSnqCKQ/qlR+vhtVE=
122
+
github.com/rachel-mp4/lrcproto v1.2.1 h1:oKP/4u8JaRzV9vY/BUn24VTrsN7pgty0S4AP8hWc/JI=
123
+
github.com/rachel-mp4/lrcproto v1.2.1/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw=
130
124
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
131
125
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
132
126
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
···
170
164
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
171
165
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
172
166
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
173
-
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
174
-
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
175
167
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
176
168
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
177
169
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+196
-1
server/internal/db/db.go
+196
-1
server/internal/db/db.go
···
6
6
"fmt"
7
7
"os"
8
8
"rvcx/internal/atputils"
9
+
"rvcx/internal/lex"
9
10
"rvcx/internal/types"
10
11
"time"
11
12
···
55
56
return did, nil
56
57
}
57
58
59
+
func (s *Store) FullResolveHandle(hdl string, ctx context.Context) (string, error) {
60
+
did, err := s.ResolveHandle(hdl, ctx)
61
+
if err == nil {
62
+
return did, nil
63
+
}
64
+
did, err = atputils.TryLookupHandle(ctx, hdl)
65
+
if err != nil {
66
+
return "", errors.New("couldn't resolve: " + err.Error())
67
+
}
68
+
s.StoreDidHandle(did, hdl, ctx)
69
+
return did, nil
70
+
}
71
+
58
72
func (s *Store) ResolveDid(did string, ctx context.Context) (string, error) {
59
73
row := s.pool.QueryRow(ctx, `SELECT h.handle FROM did_handles h WHERE h.did = $1`, did)
60
74
var handle string
···
101
115
return
102
116
}
103
117
118
+
func (s *Store) GetHistory(channelURI string, limit int, cursor *int, ctx context.Context) ([]types.SignedItemView, error) {
119
+
queryFmt := `
120
+
SELECT
121
+
'message' AS content_type,
122
+
m.uri,
123
+
m.did,
124
+
dh.handle,
125
+
p.display_name,
126
+
p.status,
127
+
p.color,
128
+
p.avatar_cid,
129
+
p.default_nick,
130
+
m.body,
131
+
NULL AS blob_cid,
132
+
NULL AS blob_mime,
133
+
NULL AS alt,
134
+
NULL AS height,
135
+
NULL AS width,
136
+
m.nick,
137
+
m.color,
138
+
s.uri,
139
+
s.issuer_did,
140
+
s.channel_uri,
141
+
s.message_id,
142
+
s.author,
143
+
s.author_handle,
144
+
s.started_at,
145
+
m.posted_at
146
+
FROM signets s
147
+
JOIN messages m ON s.uri = m.signet_uri
148
+
JOIN did_handles dh ON m.did = dh.did
149
+
JOIN profiles p ON m.did = p.did
150
+
WHERE s.channel_uri = $2 AND m.did = s.author %s
151
+
152
+
UNION ALL
153
+
154
+
SELECT
155
+
'image' AS content_type,
156
+
i.uri,
157
+
i.did,
158
+
dh.handle,
159
+
p.display_name,
160
+
p.status,
161
+
p.color,
162
+
p.avatar_cid,
163
+
p.default_nick,
164
+
NULL AS body,
165
+
i.blob_cid,
166
+
i.blob_mime,
167
+
i.alt,
168
+
i.height,
169
+
i.width,
170
+
i.nick,
171
+
i.color,
172
+
s.uri,
173
+
s.issuer_did,
174
+
s.channel_uri,
175
+
s.message_id,
176
+
s.author,
177
+
s.author_handle,
178
+
s.started_at,
179
+
i.posted_at
180
+
FROM signets s
181
+
JOIN images i ON s.uri = i.signet_uri
182
+
JOIN did_handles dh ON i.did = dh.did
183
+
JOIN profiles p ON i.did = p.did
184
+
WHERE s.channel_uri = $2 AND i.did = s.author %s
185
+
186
+
ORDER BY message_id DESC
187
+
LIMIT $1
188
+
`
189
+
var query string
190
+
if cursor != nil {
191
+
query = fmt.Sprintf(queryFmt, "AND s.message_id < $3", "AND s.message_id < $3")
192
+
return s.evalGetItems(query, ctx, limit, *cursor)
193
+
} else {
194
+
query = fmt.Sprintf(queryFmt, "", "")
195
+
return s.evalGetItems(query, ctx, limit)
196
+
}
197
+
}
198
+
func (s *Store) evalGetItems(query string, ctx context.Context, limit int, params ...any) ([]types.SignedItemView, error) {
199
+
args := []any{limit}
200
+
args = append(args, params...)
201
+
rows, err := s.pool.Query(ctx, query, args...)
202
+
if err != nil {
203
+
return nil, err
204
+
}
205
+
defer rows.Close()
206
+
var items = make([]types.SignedItemView, 0)
207
+
for rows.Next() {
208
+
var t string
209
+
var p types.ProfileView
210
+
var uri string
211
+
var body string
212
+
var image types.Image
213
+
var nick string
214
+
var color uint32
215
+
var s types.SignetView
216
+
var time time.Time
217
+
218
+
err := rows.Scan(
219
+
&t,
220
+
&uri,
221
+
&p.DID,
222
+
&p.Handle,
223
+
&p.DisplayName,
224
+
&p.Status,
225
+
&p.Color,
226
+
&p.Avatar,
227
+
&p.DefaultNick,
228
+
&body,
229
+
&image.BlobCID,
230
+
&image.BlobMIME,
231
+
&image.Alt,
232
+
&image.Height,
233
+
&image.Width,
234
+
235
+
&nick,
236
+
&color,
237
+
238
+
&s.URI,
239
+
&s.Issuer,
240
+
&s.ChannelURI,
241
+
&s.LrcId,
242
+
&s.Author,
243
+
&s.AuthorHandle,
244
+
&s.StartedAt,
245
+
&time,
246
+
)
247
+
if err != nil {
248
+
return nil, err
249
+
}
250
+
if t == "message" {
251
+
var msg types.SignedMessageView
252
+
msg.Body = body
253
+
if nick != "" {
254
+
msg.Nick = &nick
255
+
}
256
+
if color != 0 {
257
+
msg.Color = &color
258
+
}
259
+
msg.Author = p
260
+
msg.Signet = s
261
+
msg.PostedAt = time
262
+
msg.URI = uri
263
+
264
+
items = append(items, msg)
265
+
} else if t == "image" {
266
+
var img types.SignedMediaView
267
+
var imgview types.ImageView
268
+
if image.Height != nil && image.Width != nil {
269
+
var aspect lex.AspectRatio
270
+
aspect.Width = *image.Width
271
+
aspect.Height = *image.Height
272
+
imgview.AspectRatio = &aspect
273
+
}
274
+
imgview.Alt = image.Alt
275
+
base := os.Getenv("MY_IDENTITY")
276
+
src := fmt.Sprintf("https://%s/xrpc/org.xcvr.lrc.getImage?uri=%s", base, uri)
277
+
imgview.Src = &src
278
+
img.Image = &imgview
279
+
if nick != "" {
280
+
img.Nick = &nick
281
+
}
282
+
if color != 0 {
283
+
img.Color = &color
284
+
}
285
+
img.Author = p
286
+
img.Signet = s
287
+
img.PostedAt = time
288
+
img.URI = uri
289
+
290
+
items = append(items, img)
291
+
} else {
292
+
return nil, errors.New("recieved strange type t: " + t)
293
+
}
294
+
}
295
+
return items, nil
296
+
297
+
}
298
+
104
299
func (s *Store) GetMessages(channelURI string, limit int, cursor *int, ctx context.Context) ([]types.SignedMessageView, error) {
105
300
queryFmt := `
106
301
SELECT
···
168
363
&msg.Color,
169
364
170
365
&msg.Signet.URI,
171
-
&msg.Signet.IssuerHandle,
366
+
&msg.Signet.Issuer,
172
367
&msg.Signet.ChannelURI,
173
368
&msg.Signet.LrcId,
174
369
&msg.Signet.AuthorHandle,
+18
-5
server/internal/db/lexicon.go
+18
-5
server/internal/db/lexicon.go
···
220
220
return
221
221
}
222
222
223
+
// QuerySignetHandle takes a uri an queries the appropriate signet's handle.
224
+
// Deprecated: i should QuerySignetDid instead
223
225
func (s *Store) QuerySignetHandle(uri string, ctx context.Context) (string, error) {
224
226
row := s.pool.QueryRow(ctx, `SELECT s.author_handle FROM signets s WHERE s.uri = $1`, uri)
225
227
var handle string
···
228
230
return "", errors.New("BOBOBOBOBOBOL " + err.Error())
229
231
}
230
232
return handle, nil
233
+
}
234
+
func (s *Store) QuerySignetDid(uri string, ctx context.Context) (string, error) {
235
+
row := s.pool.QueryRow(ctx, `SELECT s.author FROM signets s WHERE s.uri = $1`, uri)
236
+
var did string
237
+
err := row.Scan(&did)
238
+
if err != nil {
239
+
return "", errors.New("BOBOBOBOBOBOL " + err.Error())
240
+
}
241
+
return did, nil
231
242
}
232
243
233
244
func (s *Store) QuerySignetChannelIdNum(uri string, ctx context.Context) (channelUri string, messageID uint32, err error) {
···
254
265
INSERT INTO signets (
255
266
uri,
256
267
issuer_did,
268
+
author,
257
269
author_handle,
258
270
channel_uri,
259
271
message_id,
260
272
cid,
261
273
started_at
262
274
) VALUES (
263
-
$1, $2, $3, $4, $5, $6, $7
275
+
$1, $2, $3, $4, $5, $6, $7, $8
264
276
) ON CONFLICT (uri) DO NOTHING
265
-
`, signet.URI, signet.IssuerDID, signet.AuthorHandle, signet.ChannelURI, signet.MessageID, signet.CID, signet.StartedAt)
277
+
`, signet.URI, signet.IssuerDID, signet.Author, signet.AuthorHandle, signet.ChannelURI, signet.MessageID, signet.CID, signet.StartedAt)
266
278
if err != nil {
267
279
err = errors.New("SOMETHING BAD HAPPENED: " + err.Error())
268
280
return
···
276
288
INSERT INTO signets (
277
289
uri,
278
290
issuer_did,
279
-
AuthorHandle,
291
+
author,
292
+
author_handle,
280
293
channel_uri,
281
294
message_id,
282
295
cid,
283
296
started_at
284
297
) VALUES (
285
-
$1, $2, $3, $4, $5, $6, $7
298
+
$1, $2, $3, $4, $5, $6, $7, $8
286
299
)
287
-
`, signet.URI, signet.IssuerDID, signet.AuthorHandle, signet.ChannelURI, signet.MessageID, signet.CID, signet.StartedAt)
300
+
`, signet.URI, signet.IssuerDID, signet.Author, signet.AuthorHandle, signet.ChannelURI, signet.MessageID, signet.CID, signet.StartedAt)
288
301
if err != nil {
289
302
err = errors.New("SOMETHING BAD HAPPENED: " + err.Error())
290
303
}
+1
server/internal/handler/handler.go
+1
server/internal/handler/handler.go
···
42
42
mux.HandleFunc("GET /xrpc/org.xcvr.feed.getChannels", h.WithCORS(h.getChannels))
43
43
mux.HandleFunc("GET /xrpc/org.xcvr.feed.getChannel", h.WithCORS(h.getChannel))
44
44
mux.HandleFunc("GET /xrpc/org.xcvr.lrc.getMessages", h.WithCORS(h.getMessages))
45
+
mux.HandleFunc("GET /xrpc/org.xcvr.lrc.getHistory", h.WithCORS(h.getHistory))
45
46
mux.HandleFunc("GET /xrpc/org.xcvr.lrc.getImage", h.WithCORS(h.getImage))
46
47
mux.HandleFunc("GET /xrpc/org.xcvr.actor.resolveChannel", h.WithCORS(h.resolveChannel))
47
48
mux.HandleFunc("GET /xrpc/org.xcvr.actor.getProfileView", h.WithCORS(h.getProfileView))
+55
server/internal/handler/lexiconHandlers.go
+55
server/internal/handler/lexiconHandlers.go
···
88
88
encoder.Encode(gmo)
89
89
}
90
90
91
+
func (h *Handler) getHistory(w http.ResponseWriter, r *http.Request) {
92
+
limitstr := r.URL.Query().Get("limit")
93
+
limit := 50
94
+
if limitstr != "" {
95
+
l, err := strconv.Atoi(limitstr)
96
+
if err == nil {
97
+
limit = max(min(l, 100), 1)
98
+
}
99
+
}
100
+
cursorstr := r.URL.Query().Get("cursor")
101
+
var cursor *int
102
+
if cursorstr != "" {
103
+
c, err := strconv.Atoi(cursorstr)
104
+
if err == nil {
105
+
cursor = &c
106
+
}
107
+
}
108
+
channelURI := r.URL.Query().Get("channelURI")
109
+
items, err := h.db.GetHistory(channelURI, limit, cursor, r.Context())
110
+
if err != nil {
111
+
h.serverError(w, errors.New("something went south: "+err.Error()))
112
+
return
113
+
}
114
+
if len(items) != 0 {
115
+
var signet types.SignetView
116
+
smv := items[len(items)-1]
117
+
if smv.IsMedia() {
118
+
media, _ := smv.ToSignedMediaView()
119
+
signet = media.Signet
120
+
} else if smv.IsMessage() {
121
+
message, _ := smv.ToSignedMessageView()
122
+
signet = message.Signet
123
+
} else {
124
+
h.serverError(w, errors.New("last item is invalid Signed Item"))
125
+
return
126
+
}
127
+
if int(signet.LrcId) > 2 {
128
+
cursor := strconv.Itoa(int(signet.LrcId))
129
+
w.Header().Set("Content-Type", "application/json")
130
+
jsitems, err := types.MarshalItems(items)
131
+
if err != nil {
132
+
h.serverError(w, err)
133
+
}
134
+
fmt.Fprintf(w, "{\"items\": %s, \"cursor\": %s}", jsitems, cursor)
135
+
return
136
+
}
137
+
}
138
+
w.Header().Set("Content-Type", "application/json")
139
+
jsitems, err := types.MarshalItems(items)
140
+
if err != nil {
141
+
h.serverError(w, err)
142
+
}
143
+
fmt.Fprintf(w, "{\"items\": %s}", jsitems)
144
+
}
145
+
91
146
func (h *Handler) resolveChannel(w http.ResponseWriter, r *http.Request) {
92
147
handle := r.URL.Query().Get("handle")
93
148
did := r.URL.Query().Get("did")
+77
-20
server/internal/lex/lexicons_cbor.go
+77
-20
server/internal/lex/lexicons_cbor.go
···
959
959
}
960
960
961
961
cw := cbg.NewCborWriter(w)
962
-
fieldCount := 5
962
+
fieldCount := 6
963
+
964
+
if t.AuthorHandle == nil {
965
+
fieldCount--
966
+
}
963
967
964
968
if t.StartedAt == nil {
965
969
fieldCount--
···
1004
1008
return err
1005
1009
}
1006
1010
1011
+
// t.Author (string) (string)
1012
+
if len("author") > 8192 {
1013
+
return xerrors.Errorf("Value in field \"author\" was too long")
1014
+
}
1015
+
1016
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("author"))); err != nil {
1017
+
return err
1018
+
}
1019
+
if _, err := cw.WriteString(string("author")); err != nil {
1020
+
return err
1021
+
}
1022
+
1023
+
if len(t.Author) > 8192 {
1024
+
return xerrors.Errorf("Value in field t.Author was too long")
1025
+
}
1026
+
1027
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Author))); err != nil {
1028
+
return err
1029
+
}
1030
+
if _, err := cw.WriteString(string(t.Author)); err != nil {
1031
+
return err
1032
+
}
1033
+
1007
1034
// t.StartedAt (string) (string)
1008
1035
if t.StartedAt != nil {
1009
1036
···
1060
1087
}
1061
1088
1062
1089
// t.AuthorHandle (string) (string)
1063
-
if len("authorHandle") > 8192 {
1064
-
return xerrors.Errorf("Value in field \"authorHandle\" was too long")
1065
-
}
1090
+
if t.AuthorHandle != nil {
1066
1091
1067
-
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("authorHandle"))); err != nil {
1068
-
return err
1069
-
}
1070
-
if _, err := cw.WriteString(string("authorHandle")); err != nil {
1071
-
return err
1072
-
}
1092
+
if len("authorHandle") > 8192 {
1093
+
return xerrors.Errorf("Value in field \"authorHandle\" was too long")
1094
+
}
1095
+
1096
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("authorHandle"))); err != nil {
1097
+
return err
1098
+
}
1099
+
if _, err := cw.WriteString(string("authorHandle")); err != nil {
1100
+
return err
1101
+
}
1073
1102
1074
-
if len(t.AuthorHandle) > 8192 {
1075
-
return xerrors.Errorf("Value in field t.AuthorHandle was too long")
1076
-
}
1103
+
if t.AuthorHandle == nil {
1104
+
if _, err := cw.Write(cbg.CborNull); err != nil {
1105
+
return err
1106
+
}
1107
+
} else {
1108
+
if len(*t.AuthorHandle) > 8192 {
1109
+
return xerrors.Errorf("Value in field t.AuthorHandle was too long")
1110
+
}
1077
1111
1078
-
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.AuthorHandle))); err != nil {
1079
-
return err
1080
-
}
1081
-
if _, err := cw.WriteString(string(t.AuthorHandle)); err != nil {
1082
-
return err
1112
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AuthorHandle))); err != nil {
1113
+
return err
1114
+
}
1115
+
if _, err := cw.WriteString(string(*t.AuthorHandle)); err != nil {
1116
+
return err
1117
+
}
1118
+
}
1083
1119
}
1084
1120
return nil
1085
1121
}
···
1151
1187
t.LRCID = uint64(extra)
1152
1188
1153
1189
}
1190
+
// t.Author (string) (string)
1191
+
case "author":
1192
+
1193
+
{
1194
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
1195
+
if err != nil {
1196
+
return err
1197
+
}
1198
+
1199
+
t.Author = string(sval)
1200
+
}
1154
1201
// t.StartedAt (string) (string)
1155
1202
case "startedAt":
1156
1203
···
1187
1234
case "authorHandle":
1188
1235
1189
1236
{
1190
-
sval, err := cbg.ReadStringWithMax(cr, 8192)
1237
+
b, err := cr.ReadByte()
1191
1238
if err != nil {
1192
1239
return err
1193
1240
}
1241
+
if b != cbg.CborNull[0] {
1242
+
if err := cr.UnreadByte(); err != nil {
1243
+
return err
1244
+
}
1194
1245
1195
-
t.AuthorHandle = string(sval)
1246
+
sval, err := cbg.ReadStringWithMax(cr, 8192)
1247
+
if err != nil {
1248
+
return err
1249
+
}
1250
+
1251
+
t.AuthorHandle = (*string)(&sval)
1252
+
}
1196
1253
}
1197
1254
1198
1255
default:
+2
-1
server/internal/lex/types.go
+2
-1
server/internal/lex/types.go
···
41
41
LexiconTypeID string `json:"$type,const=org.xcvr.lrc.signet" cborgen:"$type,const=org.xcvr.lrc.signet"`
42
42
ChannelURI string `json:"channelURI" cborgen:"channelURI"`
43
43
LRCID uint64 `json:"lrcID" cborgen:"lrcID"`
44
-
AuthorHandle string `json:"authorHandle" cborgen:"authorHandle"`
44
+
Author string `json:"author" cborgen:"author"`
45
+
AuthorHandle *string `json:"authorHandle,omitempty" cborgen:"authorHandle,omitempty"`
45
46
StartedAt *string `json:"startedAt,omitempty" cborgen:"startedAt,omitempty"`
46
47
}
47
48
+20
-8
server/internal/model/channel.go
+20
-8
server/internal/model/channel.go
···
34
34
welcome string
35
35
server *lrcd.Server
36
36
lastID uint32
37
-
initChan <-chan lrcpb.Event_Init
38
-
mediainitChan <-chan lrcpb.Event_Mediainit
37
+
initChan <-chan lrcd.InitChanMsg
38
+
mediainitChan <-chan lrcd.MediaInitChanMsg
39
39
ctx context.Context
40
40
cancel func()
41
41
···
164
164
m.logger.Deprintln("i think the server should exist, so i'm making it")
165
165
var err error
166
166
lastID := cm.lastID
167
-
initChan := make(chan lrcpb.Event_Init, 100)
168
-
mediainitChan := make(chan lrcpb.Event_Mediainit, 100)
167
+
initChan := make(chan lrcd.InitChanMsg, 100)
168
+
mediainitChan := make(chan lrcd.MediaInitChanMsg, 100)
169
169
170
170
server, err := lrcd.NewServer(
171
+
lrcd.WithResolver(func(externalID string, ctx context.Context) *string {
172
+
did, err := m.store.FullResolveHandle(externalID, ctx)
173
+
if err != nil {
174
+
select {
175
+
case <-ctx.Done():
176
+
return nil
177
+
default:
178
+
return &did
179
+
}
180
+
}
181
+
return &did
182
+
}),
171
183
lrcd.WithWelcome(cm.welcome),
172
184
lrcd.WithLogging(os.Stdout, true),
173
185
lrcd.WithInitialID(lastID),
···
230
242
cm.logger.Println("this is a weird case!")
231
243
return
232
244
}
233
-
err := m.rm.PostSignet(e, cm.uri, context.Background())
245
+
err := m.rm.PostSignet(e.ResolvedId, e.Init, cm.uri, context.Background())
234
246
if err != nil {
235
247
m.logger.Println("error posting signet: " + err.Error())
236
248
}
···
241
253
}
242
254
e := lrcpb.Event_Init{
243
255
Init: &lrcpb.Init{
244
-
Id: me.Mediainit.Id,
245
-
ExternalID: me.Mediainit.ExternalID,
256
+
Id: me.Mediainit.Mediainit.Id,
257
+
ExternalID: me.Mediainit.Mediainit.ExternalID,
246
258
},
247
259
}
248
-
err := m.rm.PostSignet(e, cm.uri, context.Background())
260
+
err := m.rm.PostSignet(me.ResolvedId, e, cm.uri, context.Background())
249
261
if err != nil {
250
262
m.logger.Println("error posting signet: " + err.Error())
251
263
}
+1
-1
server/internal/model/channelLexiconStream.go
+1
-1
server/internal/model/channelLexiconStream.go
+14
-7
server/internal/recordmanager/signet.go
+14
-7
server/internal/recordmanager/signet.go
···
11
11
"time"
12
12
)
13
13
14
-
func (rm *RecordManager) PostSignet(e lrcpb.Event_Init, uri string, ctx context.Context) error {
15
-
lsr, now, err := rm.validateSignet(e, uri)
14
+
func (rm *RecordManager) PostSignet(resolvedId *string, e lrcpb.Event_Init, uri string, ctx context.Context) error {
15
+
lsr, now, err := rm.validateSignet(resolvedId, e, uri, ctx)
16
16
if err != nil {
17
17
return errors.New("failed to validate signet: " + err.Error())
18
18
}
···
71
71
return rm.db.UpdateSignet(s, ctx)
72
72
}
73
73
74
-
func (rm *RecordManager) validateSignet(e lrcpb.Event_Init, uri string) (*lex.SignetRecord, *time.Time, error) {
74
+
func (rm *RecordManager) validateSignet(resolvedId *string, e lrcpb.Event_Init, uri string, ctx context.Context) (*lex.SignetRecord, *time.Time, error) {
75
75
signet := lex.SignetRecord{}
76
76
handle := e.Init.ExternalID
77
-
if handle == nil {
78
-
h := ""
79
-
handle = &h
77
+
if resolvedId == nil {
78
+
if handle != nil {
79
+
did, _ := rm.db.FullResolveHandle(*handle, ctx)
80
+
signet.Author = did
81
+
} else {
82
+
signet.Author = ""
83
+
}
84
+
} else {
85
+
signet.Author = *resolvedId
80
86
}
81
-
signet.AuthorHandle = *handle
87
+
signet.AuthorHandle = handle
82
88
if e.Init.Id == nil {
83
89
return nil, nil, errors.New("ID should not be nil")
84
90
}
···
103
109
sr := types.Signet{
104
110
URI: recorduri,
105
111
IssuerDID: atputils.GetMyDid(),
112
+
Author: lsr.Author,
106
113
AuthorHandle: lsr.AuthorHandle,
107
114
ChannelURI: lsr.ChannelURI,
108
115
MessageID: id,
+80
-3
server/internal/types/lexicons.go
+80
-3
server/internal/types/lexicons.go
···
1
1
package types
2
2
3
3
import (
4
+
"bytes"
4
5
"encoding/json"
6
+
"errors"
5
7
"rvcx/internal/lex"
6
8
"time"
7
9
)
···
111
113
type Signet struct {
112
114
URI string
113
115
IssuerDID string
114
-
AuthorHandle string
116
+
Author string
117
+
AuthorHandle *string
115
118
ChannelURI string
116
119
MessageID uint32
117
120
CID string
···
122
125
type SignetView struct {
123
126
Type string `json:"$type,const=org.xcvr.lrc.defs#signetView"`
124
127
URI string `json:"uri"`
125
-
IssuerHandle string `json:"issuerHandle"`
128
+
Issuer string `json:"issuer"`
126
129
ChannelURI string `json:"channelURI"`
127
130
LrcId uint32 `json:"lrcID"`
128
-
AuthorHandle string `json:"authorHandle"`
131
+
Author string `json:"author"`
132
+
AuthorHandle *string `json:"authorHandle,omitempty"`
129
133
StartedAt time.Time `json:"startedAt"`
130
134
}
131
135
···
286
290
Alias: (*Alias)(&m),
287
291
})
288
292
}
293
+
294
+
type SignedItemView interface {
295
+
IsMedia() bool
296
+
IsMessage() bool
297
+
ToSignedMessageView() (*SignedMessageView, error)
298
+
ToSignedMediaView() (*SignedMediaView, error)
299
+
}
300
+
301
+
func MarshalItems(items []SignedItemView) ([]byte, error) {
302
+
bb := make([][]byte, 2*len(items)+1)
303
+
bb[0] = []byte("[")
304
+
for i, item := range items {
305
+
if i != 0 {
306
+
bb[2*i] = []byte(",")
307
+
}
308
+
if item.IsMedia() {
309
+
smv, err := item.ToSignedMediaView()
310
+
if err != nil {
311
+
return nil, err
312
+
}
313
+
b, err := smv.MarshalJSON()
314
+
if err != nil {
315
+
return nil, err
316
+
}
317
+
bb[2*i+1] = b
318
+
} else if item.IsMessage() {
319
+
smv, err := item.ToSignedMessageView()
320
+
if err != nil {
321
+
return nil, err
322
+
}
323
+
b, err := smv.MarshalJSON()
324
+
if err != nil {
325
+
return nil, err
326
+
}
327
+
bb[2*i+1] = b
328
+
} else {
329
+
return nil, errors.New("item is neither media nor message")
330
+
}
331
+
}
332
+
bb[2*len(items)] = []byte("]")
333
+
return bytes.Join(bb, nil), nil
334
+
}
335
+
336
+
func (s SignedMediaView) IsMedia() bool {
337
+
return true
338
+
}
339
+
340
+
func (s SignedMessageView) IsMedia() bool {
341
+
return false
342
+
}
343
+
344
+
func (s SignedMediaView) IsMessage() bool {
345
+
return false
346
+
}
347
+
348
+
func (s SignedMessageView) IsMessage() bool {
349
+
return true
350
+
}
351
+
352
+
func (s SignedMediaView) ToSignedMessageView() (*SignedMessageView, error) {
353
+
return nil, errors.New("i am not a message")
354
+
}
355
+
356
+
func (s SignedMessageView) ToSignedMediaView() (*SignedMediaView, error) {
357
+
return nil, errors.New("i am not a media")
358
+
}
359
+
func (s SignedMessageView) ToSignedMessageView() (*SignedMessageView, error) {
360
+
return &s, nil
361
+
}
362
+
363
+
func (s SignedMediaView) ToSignedMediaView() (*SignedMediaView, error) {
364
+
return &s, nil
365
+
}