···5252 case opSend:
5353 for _, s := range em.subs {
5454 if s.filter(op.evt) {
5555- fmt.Println("outgoing event: ", op.evt)
5655 select {
5756 case s.outgoing <- op.evt:
5857 default:
+27-6
server/handlers.go
···373373 return nil, err
374374 }
375375376376- fmt.Println("notifs: ", u.Handle, len(notifs))
377376 return &appbskytypes.NotificationList_Output{
378377 Notifications: notifs,
379378 }, nil
380379}
381380382381func (s *Server) handleAppBskyNotificationUpdateSeen(ctx context.Context, input *appbskytypes.NotificationUpdateSeen_Input) error {
383383- fmt.Println("notifications not yet implemented update seen!")
382382+ u, err := s.getUser(ctx)
383383+ if err != nil {
384384+ return err
385385+ }
386386+387387+ seen, err := time.Parse(time.RFC3339, input.SeenAt)
388388+ if err != nil {
389389+ return fmt.Errorf("invalid time format for 'seenAt': %w", err)
390390+ }
384391385385- return nil
392392+ return s.notifman.UpdateSeen(ctx, u.ID, seen)
386393}
387394388395func (s *Server) handleComAtprotoAccountCreate(ctx context.Context, input *comatprototypes.AccountCreate_Input) (*comatprototypes.AccountCreate_Output, error) {
···448455}
449456450457func (s *Server) handleComAtprotoAccountCreateInviteCode(ctx context.Context, input *comatprototypes.AccountCreateInviteCode_Input) (*comatprototypes.AccountCreateInviteCode_Output, error) {
451451- panic("not yet implemented")
458458+ u, err := s.getUser(ctx)
459459+ if err != nil {
460460+ return nil, err
461461+ }
462462+463463+ return nil, fmt.Errorf("invite codes not currently supported")
452464}
453465454466func (s *Server) handleComAtprotoAccountDelete(ctx context.Context) error {
···456468}
457469458470func (s *Server) handleComAtprotoAccountGet(ctx context.Context) error {
459459- panic("not yet implemented")
471471+ return nil
460472}
461473462474func (s *Server) handleComAtprotoAccountRequestPasswordReset(ctx context.Context, input *comatprototypes.AccountRequestPasswordReset_Input) error {
···518530}
519531520532func (s *Server) handleComAtprotoRepoDeleteRecord(ctx context.Context, input *comatprototypes.RepoDeleteRecord_Input) error {
521521- panic("not yet implemented")
533533+ u, err := s.getUser(ctx)
534534+ if err != nil {
535535+ return err
536536+ }
537537+538538+ if u.Did != input.Did {
539539+ return fmt.Errorf("specified DID did not match authed user")
540540+ }
541541+542542+ return s.repoman.DeleteRecord(ctx, u.ID, input.Collection, input.Rkey)
522543}
523544524545func (s *Server) handleComAtprotoRepoDescribe(ctx context.Context, user string) (*comatprototypes.RepoDescribe_Output, error) {
+72-63
server/indexer.go
···265265 if !errors.Is(err, gorm.ErrRecordNotFound) {
266266 return err
267267 }
268268-269269- doc, err := ix.didr.GetDocument(ctx, rec.Subject.Did)
270270- if err != nil {
271271- return fmt.Errorf("could not locate DID document for followed user: %s", err)
272272- }
273273-274274- if len(doc.Service) == 0 {
275275- return fmt.Errorf("external followed user %s had no services in did document", rec.Subject.Did)
276276- }
277277-278278- svc := doc.Service[0]
279279- durl, err := url.Parse(svc.ServiceEndpoint)
280280- if err != nil {
281281- return err
282282- }
283283-284284- // TODO: the PDS's DID should also be in the service, we could use that to look up?
285285- var peering Peering
286286- if err := ix.db.First(&peering, "host = ?", durl.Host).Error; err != nil {
287287- return err
288288- }
289289-290290- var handle string
291291- if len(doc.AlsoKnownAs) > 0 {
292292- hurl, err := url.Parse(doc.AlsoKnownAs[0])
293293- if err != nil {
294294- return err
295295- }
296296-297297- handle = hurl.Host
298298- }
299299-300300- c := &xrpc.Client{Host: svc.ServiceEndpoint}
301301- profile, err := bsky.ActorGetProfile(ctx, c, rec.Subject.Did)
268268+ nu, err := ix.createExternalUser(ctx, rec.Subject.Did)
302269 if err != nil {
303270 return err
304271 }
305272306306- if handle != profile.Handle {
307307- return fmt.Errorf("mismatch in handle between did document and pds profile (%s != %s)", handle, profile.Handle)
308308- }
309309-310310- // TODO: request this users info from their server to fill out our data...
311311- u := User{
312312- Handle: handle,
313313- Did: rec.Subject.Did,
314314- PDS: peering.ID,
315315- }
316316-317317- if err := ix.db.Create(&u).Error; err != nil {
318318- return fmt.Errorf("failed to create other pds user: %w", err)
319319- }
320320-321321- // okay cool, its a user on a server we are peered with
322322- // lets make a local record of that user for the future
323323- subj = &ActorInfo{
324324- Uid: u.ID,
325325- Handle: handle,
326326- DisplayName: *profile.DisplayName,
327327- Did: rec.Subject.Did,
328328- DeclRefCid: rec.Subject.DeclarationCid, // TODO: should verify this?
329329- Type: "",
330330- PDS: peering.ID,
331331- }
332332- if err := ix.db.Create(subj).Error; err != nil {
333333- return err
334334- }
273273+ subj = nu
335274 }
336275337276 if subj.PDS != 0 {
···382321 }
383322384323 return nil
324324+}
325325+func (ix *Indexer) createExternalUser(ctx context.Context, did string) (*ActorInfo, error) {
326326+ doc, err := ix.didr.GetDocument(ctx, did)
327327+ if err != nil {
328328+ return nil, fmt.Errorf("could not locate DID document for followed user: %s", err)
329329+ }
330330+331331+ if len(doc.Service) == 0 {
332332+ return nil, fmt.Errorf("external followed user %s had no services in did document", did)
333333+ }
334334+335335+ svc := doc.Service[0]
336336+ durl, err := url.Parse(svc.ServiceEndpoint)
337337+ if err != nil {
338338+ return nil, err
339339+ }
340340+341341+ // TODO: the PDS's DID should also be in the service, we could use that to look up?
342342+ var peering Peering
343343+ if err := ix.db.First(&peering, "host = ?", durl.Host).Error; err != nil {
344344+ return nil, err
345345+ }
346346+347347+ var handle string
348348+ if len(doc.AlsoKnownAs) > 0 {
349349+ hurl, err := url.Parse(doc.AlsoKnownAs[0])
350350+ if err != nil {
351351+ return nil, err
352352+ }
353353+354354+ handle = hurl.Host
355355+ }
356356+357357+ c := &xrpc.Client{Host: svc.ServiceEndpoint}
358358+ profile, err := bsky.ActorGetProfile(ctx, c, did)
359359+ if err != nil {
360360+ return nil, err
361361+ }
362362+363363+ if handle != profile.Handle {
364364+ return nil, fmt.Errorf("mismatch in handle between did document and pds profile (%s != %s)", handle, profile.Handle)
365365+ }
366366+367367+ // TODO: request this users info from their server to fill out our data...
368368+ u := User{
369369+ Handle: handle,
370370+ Did: did,
371371+ PDS: peering.ID,
372372+ }
373373+374374+ if err := ix.db.Create(&u).Error; err != nil {
375375+ return nil, fmt.Errorf("failed to create other pds user: %w", err)
376376+ }
377377+378378+ // okay cool, its a user on a server we are peered with
379379+ // lets make a local record of that user for the future
380380+ subj := &ActorInfo{
381381+ Uid: u.ID,
382382+ Handle: handle,
383383+ DisplayName: *profile.DisplayName,
384384+ Did: did,
385385+ DeclRefCid: profile.Declaration.Cid,
386386+ Type: "",
387387+ PDS: peering.ID,
388388+ }
389389+ if err := ix.db.Create(subj).Error; err != nil {
390390+ return nil, err
391391+ }
392392+393393+ return subj, nil
385394}
386395387396func (ix *Indexer) didForUser(ctx context.Context, uid uint) (string, error) {