From 1a1187e086097b1dd75360460767b2de85fd5362 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 08 Mar 2025 17:45:28 +0000 Subject: [PATCH] add stars to tangled --- api/tangled/cbor_gen.go | 1222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- api/tangled/feedstar.go | 23 +++++++++++++++++++++++ appview/db/db.go | 10 ++++++++++ appview/db/follow.go | 17 +++++++++++------ appview/db/issues.go | 49 +++++++++++++++++++++++++++++++++++++------------ appview/db/repos.go | 31 +++++++++++++++++++++++++++++-- appview/db/star.go | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ appview/db/timeline.go | 26 ++++++++++++++++++++------ appview/pages/funcmap.go | 7 +++++++ appview/pages/pages.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- appview/pages/templates/fragments/follow.html | 17 +++++++++++++++++ appview/pages/templates/fragments/star.html | 36 ++++++++++++++++++++++++++++++++++++ appview/pages/templates/layouts/repobase.html | 30 +++++++++++++++++++----------- appview/pages/templates/timeline.html | 50 +++++++++++++++++++++++++++++++------------------- appview/pages/templates/user/profile.html | 16 ++-------------- appview/state/follow.go | 33 +++++++++++---------------------- appview/state/jetstream.go | 20 ++++++++++++++++++++ appview/state/repo.go | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------------------------- appview/state/star.go | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ appview/state/state.go | 11 +++++++++-- cmd/gen.go | 11 ++++++----- lexicons/star.json | 31 +++++++++++++++++++++++++++++++ 22 file(s) changed, 1407 insertion(s)(+), 725 deletion(s)(-) diff --git a/api/tangled/cbor_gen.go b/api/tangled/cbor_gen.go --- a/api/tangled/cbor_gen.go +++ b/api/tangled/cbor_gen.go @@ -18,7 +18,7 @@ var _ = cid.Undef var _ = math.E var _ = sort.Sort -func (t *PublicKey) MarshalCBOR(w io.Writer) error { +func (t *FeedStar) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) return err @@ -26,102 +26,79 @@ } cw := cbg.NewCborWriter(w) - if _, err := cw.Write([]byte{164}); err != nil { + if _, err := cw.Write([]byte{163}); err != nil { return err } - // t.Key (string) (string) - if len("key") > 1000000 { - return xerrors.Errorf("Value in field \"key\" was too long") + // t.LexiconTypeID (string) (string) + if len("$type") > 1000000 { + return xerrors.Errorf("Value in field \"$type\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("key"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { return err } - if _, err := cw.WriteString(string("key")); err != nil { + if _, err := cw.WriteString(string("$type")); err != nil { return err } - if len(t.Key) > 1000000 { - return xerrors.Errorf("Value in field t.Key was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Key))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.feed.star"))); err != nil { return err } - if _, err := cw.WriteString(string(t.Key)); err != nil { + if _, err := cw.WriteString(string("sh.tangled.feed.star")); err != nil { return err } - // t.Name (string) (string) - if len("name") > 1000000 { - return xerrors.Errorf("Value in field \"name\" was too long") + // t.Subject (string) (string) + if len("subject") > 1000000 { + return xerrors.Errorf("Value in field \"subject\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("name"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("subject"))); err != nil { return err } - if _, err := cw.WriteString(string("name")); err != nil { + if _, err := cw.WriteString(string("subject")); err != nil { return err } - if len(t.Name) > 1000000 { - return xerrors.Errorf("Value in field t.Name was too long") + if len(t.Subject) > 1000000 { + return xerrors.Errorf("Value in field t.Subject was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Name))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Subject))); err != nil { return err } - if _, err := cw.WriteString(string(t.Name)); err != nil { + if _, err := cw.WriteString(string(t.Subject)); err != nil { return err } - // t.LexiconTypeID (string) (string) - if len("$type") > 1000000 { - return xerrors.Errorf("Value in field \"$type\" was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { - return err - } - if _, err := cw.WriteString(string("$type")); err != nil { - return err - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.publicKey"))); err != nil { - return err - } - if _, err := cw.WriteString(string("sh.tangled.publicKey")); err != nil { - return err - } - - // t.Created (string) (string) - if len("created") > 1000000 { - return xerrors.Errorf("Value in field \"created\" was too long") + // t.CreatedAt (string) (string) + if len("createdAt") > 1000000 { + return xerrors.Errorf("Value in field \"createdAt\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("created"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("createdAt"))); err != nil { return err } - if _, err := cw.WriteString(string("created")); err != nil { + if _, err := cw.WriteString(string("createdAt")); err != nil { return err } - if len(t.Created) > 1000000 { - return xerrors.Errorf("Value in field t.Created was too long") + if len(t.CreatedAt) > 1000000 { + return xerrors.Errorf("Value in field t.CreatedAt was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Created))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.CreatedAt))); err != nil { return err } - if _, err := cw.WriteString(string(t.Created)); err != nil { + if _, err := cw.WriteString(string(t.CreatedAt)); err != nil { return err } return nil } -func (t *PublicKey) UnmarshalCBOR(r io.Reader) (err error) { - *t = PublicKey{} +func (t *FeedStar) UnmarshalCBOR(r io.Reader) (err error) { + *t = FeedStar{} cr := cbg.NewCborReader(r) @@ -140,12 +117,12 @@ return fmt.Errorf("cbor input should be of type map") } if extra > cbg.MaxLength { - return fmt.Errorf("PublicKey: map struct too large (%d)", extra) + return fmt.Errorf("FeedStar: map struct too large (%d)", extra) } n := extra - nameBuf := make([]byte, 7) + nameBuf := make([]byte, 9) for i := uint64(0); i < n; i++ { nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) if err != nil { @@ -161,19 +138,8 @@ continue } switch string(nameBuf[:nameLen]) { - // t.Key (string) (string) - case "key": - - { - sval, err := cbg.ReadStringWithMax(cr, 1000000) - if err != nil { - return err - } - - t.Key = string(sval) - } - // t.Name (string) (string) - case "name": + // t.LexiconTypeID (string) (string) + case "$type": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -181,10 +147,10 @@ if err != nil { return err } - t.Name = string(sval) + t.LexiconTypeID = string(sval) } - // t.LexiconTypeID (string) (string) - case "$type": + // t.Subject (string) (string) + case "subject": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -192,10 +158,10 @@ if err != nil { return err } - t.LexiconTypeID = string(sval) + t.Subject = string(sval) } - // t.Created (string) (string) - case "created": + // t.CreatedAt (string) (string) + case "createdAt": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -203,7 +169,7 @@ if err != nil { return err } - t.Created = string(sval) + t.CreatedAt = string(sval) } default: @@ -216,20 +182,15 @@ } return nil } -func (t *KnotMember) MarshalCBOR(w io.Writer) error { +func (t *GraphFollow) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) return err } cw := cbg.NewCborWriter(w) - fieldCount := 4 - if t.AddedAt == nil { - fieldCount-- - } - - if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { + if _, err := cw.Write([]byte{163}); err != nil { return err } @@ -245,95 +206,63 @@ if _, err := cw.WriteString(string("$type")); err != nil { return err } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.knot.member"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.graph.follow"))); err != nil { return err } - if _, err := cw.WriteString(string("sh.tangled.knot.member")); err != nil { + if _, err := cw.WriteString(string("sh.tangled.graph.follow")); err != nil { return err } - // t.Domain (string) (string) - if len("domain") > 1000000 { - return xerrors.Errorf("Value in field \"domain\" was too long") + // t.Subject (string) (string) + if len("subject") > 1000000 { + return xerrors.Errorf("Value in field \"subject\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("domain"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("subject"))); err != nil { return err } - if _, err := cw.WriteString(string("domain")); err != nil { + if _, err := cw.WriteString(string("subject")); err != nil { return err } - if len(t.Domain) > 1000000 { - return xerrors.Errorf("Value in field t.Domain was too long") + if len(t.Subject) > 1000000 { + return xerrors.Errorf("Value in field t.Subject was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Domain))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Subject))); err != nil { return err } - if _, err := cw.WriteString(string(t.Domain)); err != nil { + if _, err := cw.WriteString(string(t.Subject)); err != nil { return err } - // t.Member (string) (string) - if len("member") > 1000000 { - return xerrors.Errorf("Value in field \"member\" was too long") + // t.CreatedAt (string) (string) + if len("createdAt") > 1000000 { + return xerrors.Errorf("Value in field \"createdAt\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("member"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("createdAt"))); err != nil { return err } - if _, err := cw.WriteString(string("member")); err != nil { + if _, err := cw.WriteString(string("createdAt")); err != nil { return err } - if len(t.Member) > 1000000 { - return xerrors.Errorf("Value in field t.Member was too long") + if len(t.CreatedAt) > 1000000 { + return xerrors.Errorf("Value in field t.CreatedAt was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Member))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.CreatedAt))); err != nil { return err } - if _, err := cw.WriteString(string(t.Member)); err != nil { + if _, err := cw.WriteString(string(t.CreatedAt)); err != nil { return err } - - // t.AddedAt (string) (string) - if t.AddedAt != nil { - - if len("addedAt") > 1000000 { - return xerrors.Errorf("Value in field \"addedAt\" was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { - return err - } - if _, err := cw.WriteString(string("addedAt")); err != nil { - return err - } - - if t.AddedAt == nil { - if _, err := cw.Write(cbg.CborNull); err != nil { - return err - } - } else { - if len(*t.AddedAt) > 1000000 { - return xerrors.Errorf("Value in field t.AddedAt was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AddedAt))); err != nil { - return err - } - if _, err := cw.WriteString(string(*t.AddedAt)); err != nil { - return err - } - } - } return nil } -func (t *KnotMember) UnmarshalCBOR(r io.Reader) (err error) { - *t = KnotMember{} +func (t *GraphFollow) UnmarshalCBOR(r io.Reader) (err error) { + *t = GraphFollow{} cr := cbg.NewCborReader(r) @@ -352,12 +281,12 @@ return fmt.Errorf("cbor input should be of type map") } if extra > cbg.MaxLength { - return fmt.Errorf("KnotMember: map struct too large (%d)", extra) + return fmt.Errorf("GraphFollow: map struct too large (%d)", extra) } n := extra - nameBuf := make([]byte, 7) + nameBuf := make([]byte, 9) for i := uint64(0); i < n; i++ { nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) if err != nil { @@ -384,8 +313,8 @@ } t.LexiconTypeID = string(sval) } - // t.Domain (string) (string) - case "domain": + // t.Subject (string) (string) + case "subject": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -393,10 +322,10 @@ if err != nil { return err } - t.Domain = string(sval) + t.Subject = string(sval) } - // t.Member (string) (string) - case "member": + // t.CreatedAt (string) (string) + case "createdAt": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -404,28 +333,7 @@ if err != nil { return err } - t.Member = string(sval) - } - // t.AddedAt (string) (string) - case "addedAt": - - { - b, err := cr.ReadByte() - if err != nil { - return err - } - if b != cbg.CborNull[0] { - if err := cr.UnreadByte(); err != nil { - return err - } - - sval, err := cbg.ReadStringWithMax(cr, 1000000) - if err != nil { - return err - } - - t.AddedAt = (*string)(&sval) - } + t.CreatedAt = string(sval) } default: @@ -438,15 +346,20 @@ } return nil } -func (t *GraphFollow) MarshalCBOR(w io.Writer) error { +func (t *KnotMember) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) return err } cw := cbg.NewCborWriter(w) + fieldCount := 4 - if _, err := cw.Write([]byte{163}); err != nil { + if t.AddedAt == nil { + fieldCount-- + } + + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { return err } @@ -462,63 +375,95 @@ if _, err := cw.WriteString(string("$type")); err != nil { return err } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.graph.follow"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.knot.member"))); err != nil { return err } - if _, err := cw.WriteString(string("sh.tangled.graph.follow")); err != nil { + if _, err := cw.WriteString(string("sh.tangled.knot.member")); err != nil { return err } - // t.Subject (string) (string) - if len("subject") > 1000000 { - return xerrors.Errorf("Value in field \"subject\" was too long") + // t.Domain (string) (string) + if len("domain") > 1000000 { + return xerrors.Errorf("Value in field \"domain\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("subject"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("domain"))); err != nil { return err } - if _, err := cw.WriteString(string("subject")); err != nil { + if _, err := cw.WriteString(string("domain")); err != nil { return err } - if len(t.Subject) > 1000000 { - return xerrors.Errorf("Value in field t.Subject was too long") + if len(t.Domain) > 1000000 { + return xerrors.Errorf("Value in field t.Domain was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Subject))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Domain))); err != nil { return err } - if _, err := cw.WriteString(string(t.Subject)); err != nil { + if _, err := cw.WriteString(string(t.Domain)); err != nil { return err } - // t.CreatedAt (string) (string) - if len("createdAt") > 1000000 { - return xerrors.Errorf("Value in field \"createdAt\" was too long") + // t.Member (string) (string) + if len("member") > 1000000 { + return xerrors.Errorf("Value in field \"member\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("createdAt"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("member"))); err != nil { return err } - if _, err := cw.WriteString(string("createdAt")); err != nil { + if _, err := cw.WriteString(string("member")); err != nil { return err } - if len(t.CreatedAt) > 1000000 { - return xerrors.Errorf("Value in field t.CreatedAt was too long") + if len(t.Member) > 1000000 { + return xerrors.Errorf("Value in field t.Member was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.CreatedAt))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Member))); err != nil { return err } - if _, err := cw.WriteString(string(t.CreatedAt)); err != nil { + if _, err := cw.WriteString(string(t.Member)); err != nil { return err } + + // t.AddedAt (string) (string) + if t.AddedAt != nil { + + if len("addedAt") > 1000000 { + return xerrors.Errorf("Value in field \"addedAt\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { + return err + } + if _, err := cw.WriteString(string("addedAt")); err != nil { + return err + } + + if t.AddedAt == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if len(*t.AddedAt) > 1000000 { + return xerrors.Errorf("Value in field t.AddedAt was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AddedAt))); err != nil { + return err + } + if _, err := cw.WriteString(string(*t.AddedAt)); err != nil { + return err + } + } + } return nil } -func (t *GraphFollow) UnmarshalCBOR(r io.Reader) (err error) { - *t = GraphFollow{} +func (t *KnotMember) UnmarshalCBOR(r io.Reader) (err error) { + *t = KnotMember{} cr := cbg.NewCborReader(r) @@ -537,12 +482,12 @@ return fmt.Errorf("cbor input should be of type map") } if extra > cbg.MaxLength { - return fmt.Errorf("GraphFollow: map struct too large (%d)", extra) + return fmt.Errorf("KnotMember: map struct too large (%d)", extra) } n := extra - nameBuf := make([]byte, 9) + nameBuf := make([]byte, 7) for i := uint64(0); i < n; i++ { nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) if err != nil { @@ -569,8 +514,8 @@ } t.LexiconTypeID = string(sval) } - // t.Subject (string) (string) - case "subject": + // t.Domain (string) (string) + case "domain": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -578,10 +523,10 @@ if err != nil { return err } - t.Subject = string(sval) + t.Domain = string(sval) } - // t.CreatedAt (string) (string) - case "createdAt": + // t.Member (string) (string) + case "member": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -589,7 +534,28 @@ if err != nil { return err } - t.CreatedAt = string(sval) + t.Member = string(sval) + } + // t.AddedAt (string) (string) + case "addedAt": + + { + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + + sval, err := cbg.ReadStringWithMax(cr, 1000000) + if err != nil { + return err + } + + t.AddedAt = (*string)(&sval) + } } default: @@ -602,43 +568,38 @@ } return nil } -func (t *Repo) MarshalCBOR(w io.Writer) error { +func (t *PublicKey) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) return err } cw := cbg.NewCborWriter(w) - fieldCount := 5 - if t.AddedAt == nil { - fieldCount-- - } - - if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { + if _, err := cw.Write([]byte{164}); err != nil { return err } - // t.Knot (string) (string) - if len("knot") > 1000000 { - return xerrors.Errorf("Value in field \"knot\" was too long") + // t.Key (string) (string) + if len("key") > 1000000 { + return xerrors.Errorf("Value in field \"key\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("knot"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("key"))); err != nil { return err } - if _, err := cw.WriteString(string("knot")); err != nil { + if _, err := cw.WriteString(string("key")); err != nil { return err } - if len(t.Knot) > 1000000 { - return xerrors.Errorf("Value in field t.Knot was too long") + if len(t.Key) > 1000000 { + return xerrors.Errorf("Value in field t.Key was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Knot))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Key))); err != nil { return err } - if _, err := cw.WriteString(string(t.Knot)); err != nil { + if _, err := cw.WriteString(string(t.Key)); err != nil { return err } @@ -677,72 +638,40 @@ if _, err := cw.WriteString(string("$type")); err != nil { return err } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.publicKey"))); err != nil { return err } - if _, err := cw.WriteString(string("sh.tangled.repo")); err != nil { + if _, err := cw.WriteString(string("sh.tangled.publicKey")); err != nil { return err } - // t.Owner (string) (string) - if len("owner") > 1000000 { - return xerrors.Errorf("Value in field \"owner\" was too long") + // t.Created (string) (string) + if len("created") > 1000000 { + return xerrors.Errorf("Value in field \"created\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("created"))); err != nil { return err } - if _, err := cw.WriteString(string("owner")); err != nil { + if _, err := cw.WriteString(string("created")); err != nil { return err } - if len(t.Owner) > 1000000 { - return xerrors.Errorf("Value in field t.Owner was too long") + if len(t.Created) > 1000000 { + return xerrors.Errorf("Value in field t.Created was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Created))); err != nil { return err } - if _, err := cw.WriteString(string(t.Owner)); err != nil { + if _, err := cw.WriteString(string(t.Created)); err != nil { return err } - - // t.AddedAt (string) (string) - if t.AddedAt != nil { - - if len("addedAt") > 1000000 { - return xerrors.Errorf("Value in field \"addedAt\" was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { - return err - } - if _, err := cw.WriteString(string("addedAt")); err != nil { - return err - } - - if t.AddedAt == nil { - if _, err := cw.Write(cbg.CborNull); err != nil { - return err - } - } else { - if len(*t.AddedAt) > 1000000 { - return xerrors.Errorf("Value in field t.AddedAt was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AddedAt))); err != nil { - return err - } - if _, err := cw.WriteString(string(*t.AddedAt)); err != nil { - return err - } - } - } return nil } -func (t *Repo) UnmarshalCBOR(r io.Reader) (err error) { - *t = Repo{} +func (t *PublicKey) UnmarshalCBOR(r io.Reader) (err error) { + *t = PublicKey{} cr := cbg.NewCborReader(r) @@ -761,7 +690,7 @@ return fmt.Errorf("cbor input should be of type map") } if extra > cbg.MaxLength { - return fmt.Errorf("Repo: map struct too large (%d)", extra) + return fmt.Errorf("PublicKey: map struct too large (%d)", extra) } n := extra @@ -782,8 +711,8 @@ continue } switch string(nameBuf[:nameLen]) { - // t.Knot (string) (string) - case "knot": + // t.Key (string) (string) + case "key": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -791,7 +720,7 @@ if err != nil { return err } - t.Knot = string(sval) + t.Key = string(sval) } // t.Name (string) (string) case "name": @@ -815,8 +744,8 @@ } t.LexiconTypeID = string(sval) } - // t.Owner (string) (string) - case "owner": + // t.Created (string) (string) + case "created": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -824,28 +753,7 @@ if err != nil { return err } - t.Owner = string(sval) - } - // t.AddedAt (string) (string) - case "addedAt": - - { - b, err := cr.ReadByte() - if err != nil { - return err - } - if b != cbg.CborNull[0] { - if err := cr.UnreadByte(); err != nil { - return err - } - - sval, err := cbg.ReadStringWithMax(cr, 1000000) - if err != nil { - return err - } - - t.AddedAt = (*string)(&sval) - } + t.Created = string(sval) } default: @@ -858,7 +766,7 @@ } return nil } -func (t *RepoIssue) MarshalCBOR(w io.Writer) error { +func (t *RepoIssueComment) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) return err @@ -871,7 +779,19 @@ if t.Body == nil { fieldCount-- } + if t.CommentId == nil { + fieldCount-- + } + if t.CreatedAt == nil { + fieldCount-- + } + + if t.Owner == nil { + fieldCount-- + } + + if t.Repo == nil { fieldCount-- } @@ -912,26 +832,35 @@ } } // t.Repo (string) (string) - if len("repo") > 1000000 { - return xerrors.Errorf("Value in field \"repo\" was too long") - } + if t.Repo != nil { - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("repo"))); err != nil { - return err - } - if _, err := cw.WriteString(string("repo")); err != nil { - return err - } + if len("repo") > 1000000 { + return xerrors.Errorf("Value in field \"repo\" was too long") + } - if len(t.Repo) > 1000000 { - return xerrors.Errorf("Value in field t.Repo was too long") - } + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("repo"))); err != nil { + return err + } + if _, err := cw.WriteString(string("repo")); err != nil { + return err + } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Repo))); err != nil { - return err - } - if _, err := cw.WriteString(string(t.Repo)); err != nil { - return err + if t.Repo == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if len(*t.Repo) > 1000000 { + return xerrors.Errorf("Value in field t.Repo was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Repo))); err != nil { + return err + } + if _, err := cw.WriteString(string(*t.Repo)); err != nil { + return err + } + } } // t.LexiconTypeID (string) (string) @@ -946,79 +875,98 @@ if _, err := cw.WriteString(string("$type")); err != nil { return err } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo.issue"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo.issue.comment"))); err != nil { return err } - if _, err := cw.WriteString(string("sh.tangled.repo.issue")); err != nil { + if _, err := cw.WriteString(string("sh.tangled.repo.issue.comment")); err != nil { return err } - // t.Owner (string) (string) - if len("owner") > 1000000 { - return xerrors.Errorf("Value in field \"owner\" was too long") + // t.Issue (string) (string) + if len("issue") > 1000000 { + return xerrors.Errorf("Value in field \"issue\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issue"))); err != nil { return err } - if _, err := cw.WriteString(string("owner")); err != nil { + if _, err := cw.WriteString(string("issue")); err != nil { return err } - if len(t.Owner) > 1000000 { - return xerrors.Errorf("Value in field t.Owner was too long") + if len(t.Issue) > 1000000 { + return xerrors.Errorf("Value in field t.Issue was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Issue))); err != nil { return err } - if _, err := cw.WriteString(string(t.Owner)); err != nil { + if _, err := cw.WriteString(string(t.Issue)); err != nil { return err } - // t.Title (string) (string) - if len("title") > 1000000 { - return xerrors.Errorf("Value in field \"title\" was too long") - } + // t.Owner (string) (string) + if t.Owner != nil { - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("title"))); err != nil { - return err - } - if _, err := cw.WriteString(string("title")); err != nil { - return err - } + if len("owner") > 1000000 { + return xerrors.Errorf("Value in field \"owner\" was too long") + } - if len(t.Title) > 1000000 { - return xerrors.Errorf("Value in field t.Title was too long") - } + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { + return err + } + if _, err := cw.WriteString(string("owner")); err != nil { + return err + } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Title))); err != nil { - return err - } - if _, err := cw.WriteString(string(t.Title)); err != nil { - return err - } + if t.Owner == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if len(*t.Owner) > 1000000 { + return xerrors.Errorf("Value in field t.Owner was too long") + } - // t.IssueId (int64) (int64) - if len("issueId") > 1000000 { - return xerrors.Errorf("Value in field \"issueId\" was too long") + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Owner))); err != nil { + return err + } + if _, err := cw.WriteString(string(*t.Owner)); err != nil { + return err + } + } } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issueId"))); err != nil { - return err - } - if _, err := cw.WriteString(string("issueId")); err != nil { - return err - } + // t.CommentId (int64) (int64) + if t.CommentId != nil { - if t.IssueId >= 0 { - if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.IssueId)); err != nil { + if len("commentId") > 1000000 { + return xerrors.Errorf("Value in field \"commentId\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("commentId"))); err != nil { return err } - } else { - if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.IssueId-1)); err != nil { + if _, err := cw.WriteString(string("commentId")); err != nil { return err } + + if t.CommentId == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if *t.CommentId >= 0 { + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.CommentId)); err != nil { + return err + } + } else { + if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-*t.CommentId-1)); err != nil { + return err + } + } + } + } // t.CreatedAt (string) (string) @@ -1055,8 +1003,8 @@ } return nil } -func (t *RepoIssue) UnmarshalCBOR(r io.Reader) (err error) { - *t = RepoIssue{} +func (t *RepoIssueComment) UnmarshalCBOR(r io.Reader) (err error) { + *t = RepoIssueComment{} cr := cbg.NewCborReader(r) @@ -1075,7 +1023,7 @@ return fmt.Errorf("cbor input should be of type map") } if extra > cbg.MaxLength { - return fmt.Errorf("RepoIssue: map struct too large (%d)", extra) + return fmt.Errorf("RepoIssueComment: map struct too large (%d)", extra) } n := extra @@ -1121,12 +1069,22 @@ // t.Repo (string) (string) case "repo": { - sval, err := cbg.ReadStringWithMax(cr, 1000000) + b, err := cr.ReadByte() if err != nil { return err } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } - t.Repo = string(sval) + sval, err := cbg.ReadStringWithMax(cr, 1000000) + if err != nil { + return err + } + + t.Repo = (*string)(&sval) + } } // t.LexiconTypeID (string) (string) case "$type": @@ -1139,8 +1097,8 @@ } t.LexiconTypeID = string(sval) } - // t.Owner (string) (string) - case "owner": + // t.Issue (string) (string) + case "issue": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -1148,44 +1106,64 @@ if err != nil { return err } - t.Owner = string(sval) + t.Issue = string(sval) } - // t.Title (string) (string) - case "title": + // t.Owner (string) (string) + case "owner": { - sval, err := cbg.ReadStringWithMax(cr, 1000000) + b, err := cr.ReadByte() if err != nil { return err } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } - t.Title = string(sval) + sval, err := cbg.ReadStringWithMax(cr, 1000000) + if err != nil { + return err + } + + t.Owner = (*string)(&sval) + } } - // t.IssueId (int64) (int64) - case "issueId": + // t.CommentId (int64) (int64) + case "commentId": { - maj, extra, err := cr.ReadHeader() + + b, err := cr.ReadByte() if err != nil { return err } - var extraI int64 - switch maj { - case cbg.MajUnsignedInt: - extraI = int64(extra) - if extraI < 0 { - return fmt.Errorf("int64 positive overflow") + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err } - case cbg.MajNegativeInt: - extraI = int64(extra) - if extraI < 0 { - return fmt.Errorf("int64 negative overflow") + maj, extra, err := cr.ReadHeader() + if err != nil { + return err } - extraI = -1 - extraI - default: - return fmt.Errorf("wrong type for int64 field: %d", maj) - } + var extraI int64 + switch maj { + case cbg.MajUnsignedInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 positive overflow") + } + case cbg.MajNegativeInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 negative overflow") + } + extraI = -1 - extraI + default: + return fmt.Errorf("wrong type for int64 field: %d", maj) + } - t.IssueId = int64(extraI) + t.CommentId = (*int64)(&extraI) + } } // t.CreatedAt (string) (string) case "createdAt": @@ -1407,7 +1385,7 @@ } return nil } -func (t *RepoIssueComment) MarshalCBOR(w io.Writer) error { +func (t *RepoIssue) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) return err @@ -1420,19 +1398,7 @@ if t.Body == nil { fieldCount-- } - if t.CommentId == nil { - fieldCount-- - } - if t.CreatedAt == nil { - fieldCount-- - } - - if t.Owner == nil { - fieldCount-- - } - - if t.Repo == nil { fieldCount-- } @@ -1473,35 +1439,26 @@ } } // t.Repo (string) (string) - if t.Repo != nil { - - if len("repo") > 1000000 { - return xerrors.Errorf("Value in field \"repo\" was too long") - } + if len("repo") > 1000000 { + return xerrors.Errorf("Value in field \"repo\" was too long") + } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("repo"))); err != nil { - return err - } - if _, err := cw.WriteString(string("repo")); err != nil { - return err - } + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("repo"))); err != nil { + return err + } + if _, err := cw.WriteString(string("repo")); err != nil { + return err + } - if t.Repo == nil { - if _, err := cw.Write(cbg.CborNull); err != nil { - return err - } - } else { - if len(*t.Repo) > 1000000 { - return xerrors.Errorf("Value in field t.Repo was too long") - } + if len(t.Repo) > 1000000 { + return xerrors.Errorf("Value in field t.Repo was too long") + } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Repo))); err != nil { - return err - } - if _, err := cw.WriteString(string(*t.Repo)); err != nil { - return err - } - } + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Repo))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.Repo)); err != nil { + return err } // t.LexiconTypeID (string) (string) @@ -1516,98 +1473,79 @@ if _, err := cw.WriteString(string("$type")); err != nil { return err } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo.issue.comment"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo.issue"))); err != nil { return err } - if _, err := cw.WriteString(string("sh.tangled.repo.issue.comment")); err != nil { + if _, err := cw.WriteString(string("sh.tangled.repo.issue")); err != nil { return err } - // t.Issue (string) (string) - if len("issue") > 1000000 { - return xerrors.Errorf("Value in field \"issue\" was too long") + // t.Owner (string) (string) + if len("owner") > 1000000 { + return xerrors.Errorf("Value in field \"owner\" was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issue"))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { return err } - if _, err := cw.WriteString(string("issue")); err != nil { + if _, err := cw.WriteString(string("owner")); err != nil { return err } - if len(t.Issue) > 1000000 { - return xerrors.Errorf("Value in field t.Issue was too long") + if len(t.Owner) > 1000000 { + return xerrors.Errorf("Value in field t.Owner was too long") } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Issue))); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil { return err } - if _, err := cw.WriteString(string(t.Issue)); err != nil { + if _, err := cw.WriteString(string(t.Owner)); err != nil { return err } - // t.Owner (string) (string) - if t.Owner != nil { + // t.Title (string) (string) + if len("title") > 1000000 { + return xerrors.Errorf("Value in field \"title\" was too long") + } - if len("owner") > 1000000 { - return xerrors.Errorf("Value in field \"owner\" was too long") - } + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("title"))); err != nil { + return err + } + if _, err := cw.WriteString(string("title")); err != nil { + return err + } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { - return err - } - if _, err := cw.WriteString(string("owner")); err != nil { - return err - } + if len(t.Title) > 1000000 { + return xerrors.Errorf("Value in field t.Title was too long") + } - if t.Owner == nil { - if _, err := cw.Write(cbg.CborNull); err != nil { - return err - } - } else { - if len(*t.Owner) > 1000000 { - return xerrors.Errorf("Value in field t.Owner was too long") - } + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Title))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.Title)); err != nil { + return err + } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Owner))); err != nil { - return err - } - if _, err := cw.WriteString(string(*t.Owner)); err != nil { - return err - } - } + // t.IssueId (int64) (int64) + if len("issueId") > 1000000 { + return xerrors.Errorf("Value in field \"issueId\" was too long") } - // t.CommentId (int64) (int64) - if t.CommentId != nil { - - if len("commentId") > 1000000 { - return xerrors.Errorf("Value in field \"commentId\" was too long") - } + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issueId"))); err != nil { + return err + } + if _, err := cw.WriteString(string("issueId")); err != nil { + return err + } - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("commentId"))); err != nil { + if t.IssueId >= 0 { + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.IssueId)); err != nil { return err } - if _, err := cw.WriteString(string("commentId")); err != nil { + } else { + if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.IssueId-1)); err != nil { return err } - - if t.CommentId == nil { - if _, err := cw.Write(cbg.CborNull); err != nil { - return err - } - } else { - if *t.CommentId >= 0 { - if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.CommentId)); err != nil { - return err - } - } else { - if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-*t.CommentId-1)); err != nil { - return err - } - } - } - } // t.CreatedAt (string) (string) @@ -1644,8 +1582,8 @@ } return nil } -func (t *RepoIssueComment) UnmarshalCBOR(r io.Reader) (err error) { - *t = RepoIssueComment{} +func (t *RepoIssue) UnmarshalCBOR(r io.Reader) (err error) { + *t = RepoIssue{} cr := cbg.NewCborReader(r) @@ -1664,7 +1602,7 @@ return fmt.Errorf("cbor input should be of type map") } if extra > cbg.MaxLength { - return fmt.Errorf("RepoIssueComment: map struct too large (%d)", extra) + return fmt.Errorf("RepoIssue: map struct too large (%d)", extra) } n := extra @@ -1710,22 +1648,12 @@ // t.Repo (string) (string) case "repo": { - b, err := cr.ReadByte() + sval, err := cbg.ReadStringWithMax(cr, 1000000) if err != nil { return err } - if b != cbg.CborNull[0] { - if err := cr.UnreadByte(); err != nil { - return err - } - sval, err := cbg.ReadStringWithMax(cr, 1000000) - if err != nil { - return err - } - - t.Repo = (*string)(&sval) - } + t.Repo = string(sval) } // t.LexiconTypeID (string) (string) case "$type": @@ -1738,8 +1666,19 @@ } t.LexiconTypeID = string(sval) } - // t.Issue (string) (string) - case "issue": + // t.Owner (string) (string) + case "owner": + + { + sval, err := cbg.ReadStringWithMax(cr, 1000000) + if err != nil { + return err + } + + t.Owner = string(sval) + } + // t.Title (string) (string) + case "title": { sval, err := cbg.ReadStringWithMax(cr, 1000000) @@ -1747,10 +1686,36 @@ if err != nil { return err } - t.Issue = string(sval) + t.Title = string(sval) + } + // t.IssueId (int64) (int64) + case "issueId": + { + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + var extraI int64 + switch maj { + case cbg.MajUnsignedInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 positive overflow") + } + case cbg.MajNegativeInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 negative overflow") + } + extraI = -1 - extraI + default: + return fmt.Errorf("wrong type for int64 field: %d", maj) + } + + t.IssueId = int64(extraI) } - // t.Owner (string) (string) - case "owner": + // t.CreatedAt (string) (string) + case "createdAt": { b, err := cr.ReadByte() @@ -1767,47 +1732,246 @@ if err != nil { return err } - t.Owner = (*string)(&sval) + t.CreatedAt = (*string)(&sval) + } + } + + default: + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { + return err + } + } + } + + return nil +} +func (t *Repo) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + fieldCount := 5 + + if t.AddedAt == nil { + fieldCount-- + } + + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { + return err + } + + // t.Knot (string) (string) + if len("knot") > 1000000 { + return xerrors.Errorf("Value in field \"knot\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("knot"))); err != nil { + return err + } + if _, err := cw.WriteString(string("knot")); err != nil { + return err + } + + if len(t.Knot) > 1000000 { + return xerrors.Errorf("Value in field t.Knot was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Knot))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.Knot)); err != nil { + return err + } + + // t.Name (string) (string) + if len("name") > 1000000 { + return xerrors.Errorf("Value in field \"name\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("name"))); err != nil { + return err + } + if _, err := cw.WriteString(string("name")); err != nil { + return err + } + + if len(t.Name) > 1000000 { + return xerrors.Errorf("Value in field t.Name was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Name))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.Name)); err != nil { + return err + } + + // t.LexiconTypeID (string) (string) + if len("$type") > 1000000 { + return xerrors.Errorf("Value in field \"$type\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { + return err + } + if _, err := cw.WriteString(string("$type")); err != nil { + return err + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo"))); err != nil { + return err + } + if _, err := cw.WriteString(string("sh.tangled.repo")); err != nil { + return err + } + + // t.Owner (string) (string) + if len("owner") > 1000000 { + return xerrors.Errorf("Value in field \"owner\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { + return err + } + if _, err := cw.WriteString(string("owner")); err != nil { + return err + } + + if len(t.Owner) > 1000000 { + return xerrors.Errorf("Value in field t.Owner was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil { + return err + } + if _, err := cw.WriteString(string(t.Owner)); err != nil { + return err + } + + // t.AddedAt (string) (string) + if t.AddedAt != nil { + + if len("addedAt") > 1000000 { + return xerrors.Errorf("Value in field \"addedAt\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { + return err + } + if _, err := cw.WriteString(string("addedAt")); err != nil { + return err + } + + if t.AddedAt == nil { + if _, err := cw.Write(cbg.CborNull); err != nil { + return err + } + } else { + if len(*t.AddedAt) > 1000000 { + return xerrors.Errorf("Value in field t.AddedAt was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AddedAt))); err != nil { + return err + } + if _, err := cw.WriteString(string(*t.AddedAt)); err != nil { + return err + } + } + } + return nil +} + +func (t *Repo) UnmarshalCBOR(r io.Reader) (err error) { + *t = Repo{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("Repo: map struct too large (%d)", extra) + } + + n := extra + + nameBuf := make([]byte, 7) + for i := uint64(0); i < n; i++ { + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) + if err != nil { + return err + } + + if !ok { + // Field doesn't exist on this type, so ignore it + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { + return err + } + continue + } + + switch string(nameBuf[:nameLen]) { + // t.Knot (string) (string) + case "knot": + + { + sval, err := cbg.ReadStringWithMax(cr, 1000000) + if err != nil { + return err } + + t.Knot = string(sval) } - // t.CommentId (int64) (int64) - case "commentId": + // t.Name (string) (string) + case "name": + { + sval, err := cbg.ReadStringWithMax(cr, 1000000) + if err != nil { + return err + } - b, err := cr.ReadByte() + t.Name = string(sval) + } + // t.LexiconTypeID (string) (string) + case "$type": + + { + sval, err := cbg.ReadStringWithMax(cr, 1000000) if err != nil { return err } - if b != cbg.CborNull[0] { - if err := cr.UnreadByte(); err != nil { - return err - } - maj, extra, err := cr.ReadHeader() - if err != nil { - return err - } - var extraI int64 - switch maj { - case cbg.MajUnsignedInt: - extraI = int64(extra) - if extraI < 0 { - return fmt.Errorf("int64 positive overflow") - } - case cbg.MajNegativeInt: - extraI = int64(extra) - if extraI < 0 { - return fmt.Errorf("int64 negative overflow") - } - extraI = -1 - extraI - default: - return fmt.Errorf("wrong type for int64 field: %d", maj) - } - t.CommentId = (*int64)(&extraI) + t.LexiconTypeID = string(sval) + } + // t.Owner (string) (string) + case "owner": + + { + sval, err := cbg.ReadStringWithMax(cr, 1000000) + if err != nil { + return err } + + t.Owner = string(sval) } - // t.CreatedAt (string) (string) - case "createdAt": + // t.AddedAt (string) (string) + case "addedAt": { b, err := cr.ReadByte() @@ -1824,7 +1988,7 @@ if err != nil { return err } - t.CreatedAt = (*string)(&sval) + t.AddedAt = (*string)(&sval) } } diff --git a/api/tangled/feedstar.go b/api/tangled/feedstar.go new file mode 100644 --- /dev/null +++ b/api/tangled/feedstar.go @@ -0,0 +1,23 @@ +// Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT. + +package tangled + +// schema: sh.tangled.feed.star + +import ( + "github.com/bluesky-social/indigo/lex/util" +) + +const ( + FeedStarNSID = "sh.tangled.feed.star" +) + +func init() { + util.RegisterType("sh.tangled.feed.star", &FeedStar{}) +} // +// RECORDTYPE: FeedStar +type FeedStar struct { + LexiconTypeID string `json:"$type,const=sh.tangled.feed.star" cborgen:"$type,const=sh.tangled.feed.star"` + CreatedAt string `json:"createdAt" cborgen:"createdAt"` + Subject string `json:"subject" cborgen:"subject"` +} diff --git a/appview/db/db.go b/appview/db/db.go --- a/appview/db/db.go +++ b/appview/db/db.go @@ -112,6 +112,16 @@ repo_at text primary key, next_issue_id integer not null default 1 ); + create table if not exists stars ( + id integer primary key autoincrement, + starred_by_did text not null, + repo_at text not null, + rkey text not null, + created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), + foreign key (repo_at) references repos(at_uri) on delete cascade, + unique(starred_by_did, repo_at) + ); + `) if err != nil { return nil, err diff --git a/appview/db/follow.go b/appview/db/follow.go --- a/appview/db/follow.go +++ b/appview/db/follow.go @@ -9,7 +9,7 @@ type Follow struct { UserDid string SubjectDid string FollowedAt time.Time - RKey string + Rkey string } func AddFollow(e Execer, userDid, subjectDid, rkey string) error { @@ -25,7 +25,7 @@ row := e.QueryRow(query, userDid, subjectDid) var follow Follow var followedAt string - err := row.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.RKey) + err := row.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.Rkey) if err != nil { return nil, err } @@ -41,7 +41,7 @@ return &follow, nil } -// Get a follow record +// Remove a follow func DeleteFollow(e Execer, userDid, subjectDid string) error { _, err := e.Exec(`delete from follows where user_did = ? and subject_did = ?`, userDid, subjectDid) return err @@ -91,10 +91,15 @@ return IsFollowing } } -func GetAllFollows(e Execer) ([]Follow, error) { +func GetAllFollows(e Execer, limit int) ([]Follow, error) { var follows []Follow - rows, err := e.Query(`select user_did, subject_did, followed_at, rkey from follows`) + rows, err := e.Query(` + select user_did, subject_did, followed_at, rkey + from follows + order by followed_at desc + limit ?`, limit, + ) if err != nil { return nil, err } @@ -103,7 +108,7 @@ for rows.Next() { var follow Follow var followedAt string - if err := rows.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.RKey); err != nil { + if err := rows.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.Rkey); err != nil { return nil, err } diff --git a/appview/db/issues.go b/appview/db/issues.go --- a/appview/db/issues.go +++ b/appview/db/issues.go @@ -3,10 +3,12 @@ import ( "database/sql" "time" + + "github.com/bluesky-social/indigo/atproto/syntax" ) type Issue struct { - RepoAt string + RepoAt syntax.ATURI OwnerDid string IssueId int IssueAt string @@ -18,7 +20,7 @@ } type Comment struct { OwnerDid string - RepoAt string + RepoAt syntax.ATURI CommentAt string Issue int CommentId int @@ -65,30 +67,30 @@ return nil } -func SetIssueAt(e Execer, repoAt string, issueId int, issueAt string) error { +func SetIssueAt(e Execer, repoAt syntax.ATURI, issueId int, issueAt string) error { _, err := e.Exec(`update issues set issue_at = ? where repo_at = ? and issue_id = ?`, issueAt, repoAt, issueId) return err } -func GetIssueAt(e Execer, repoAt string, issueId int) (string, error) { +func GetIssueAt(e Execer, repoAt syntax.ATURI, issueId int) (string, error) { var issueAt string err := e.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt) return issueAt, err } -func GetIssueId(e Execer, repoAt string) (int, error) { +func GetIssueId(e Execer, repoAt syntax.ATURI) (int, error) { var issueId int err := e.QueryRow(`select next_issue_id from repo_issue_seqs where repo_at = ?`, repoAt).Scan(&issueId) return issueId - 1, err } -func GetIssueOwnerDid(e Execer, repoAt string, issueId int) (string, error) { +func GetIssueOwnerDid(e Execer, repoAt syntax.ATURI, issueId int) (string, error) { var ownerDid string err := e.QueryRow(`select owner_did from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&ownerDid) return ownerDid, err } -func GetIssues(e Execer, repoAt string) ([]Issue, error) { +func GetIssues(e Execer, repoAt syntax.ATURI) ([]Issue, error) { var issues []Issue rows, err := e.Query(`select owner_did, issue_id, created, title, body, open from issues where repo_at = ? order by created desc`, repoAt) @@ -121,7 +123,7 @@ return issues, nil } -func GetIssue(e Execer, repoAt string, issueId int) (*Issue, error) { +func GetIssue(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, error) { query := `select owner_did, created, title, body, open from issues where repo_at = ? and issue_id = ?` row := e.QueryRow(query, repoAt, issueId) @@ -141,7 +143,7 @@ return &issue, nil } -func GetIssueWithComments(e Execer, repoAt string, issueId int) (*Issue, []Comment, error) { +func GetIssueWithComments(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, []Comment, error) { query := `select owner_did, issue_id, created, title, body, open from issues where repo_at = ? and issue_id = ?` row := e.QueryRow(query, repoAt, issueId) @@ -180,7 +182,7 @@ ) return err } -func GetComments(e Execer, repoAt string, issueId int) ([]Comment, error) { +func GetComments(e Execer, repoAt syntax.ATURI, issueId int) ([]Comment, error) { var comments []Comment rows, err := e.Query(`select owner_did, issue_id, comment_id, comment_at, body, created from comments where repo_at = ? and issue_id = ? order by created asc`, repoAt, issueId) @@ -216,12 +218,35 @@ return comments, nil } -func CloseIssue(e Execer, repoAt string, issueId int) error { +func CloseIssue(e Execer, repoAt syntax.ATURI, issueId int) error { _, err := e.Exec(`update issues set open = 0 where repo_at = ? and issue_id = ?`, repoAt, issueId) return err } -func ReopenIssue(e Execer, repoAt string, issueId int) error { +func ReopenIssue(e Execer, repoAt syntax.ATURI, issueId int) error { _, err := e.Exec(`update issues set open = 1 where repo_at = ? and issue_id = ?`, repoAt, issueId) return err } + +type IssueCount struct { + Open int + Closed int +} + +func GetIssueCount(e Execer, repoAt syntax.ATURI) (IssueCount, error) { + row := e.QueryRow(` + select + count(case when open = 1 then 1 end) as open_count, + count(case when open = 0 then 1 end) as closed_count + from issues + where repo_at = ?`, + repoAt, + ) + + var count IssueCount + if err := row.Scan(&count.Open, &count.Closed); err != nil { + return IssueCount{0, 0}, err + } + + return count, nil +} diff --git a/appview/db/repos.go b/appview/db/repos.go --- a/appview/db/repos.go +++ b/appview/db/repos.go @@ -14,10 +14,17 @@ Created time.Time AtUri string } -func GetAllRepos(e Execer) ([]Repo, error) { +func GetAllRepos(e Execer, limit int) ([]Repo, error) { var repos []Repo - rows, err := e.Query(`select did, name, knot, rkey, created from repos`) + rows, err := e.Query( + `select did, name, knot, rkey, created + from repos + order by created desc + limit ? + `, + limit, + ) if err != nil { return nil, err } @@ -79,6 +86,21 @@ return &repo, nil } +func GetRepoByAtUri(e Execer, atUri string) (*Repo, error) { + var repo Repo + + row := e.QueryRow(`select did, name, knot, created, at_uri from repos where at_uri = ?`, atUri) + + var createdAt string + if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri); err != nil { + return nil, err + } + createdAtTime, _ := time.Parse(time.RFC3339, createdAt) + repo.Created = createdAtTime + + return &repo, nil +} + func AddRepo(e Execer, repo *Repo) error { _, err := e.Exec(`insert into repos (did, name, knot, rkey, at_uri) values (?, ?, ?, ?, ?)`, repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri) return err @@ -120,6 +142,11 @@ return nil, err } return repos, nil +} + +type RepoStats struct { + StarCount int + IssueCount IssueCount } func scanRepo(rows *sql.Rows, did, name, knot, rkey *string, created *time.Time) error { diff --git a/appview/db/star.go b/appview/db/star.go new file mode 100644 --- /dev/null +++ b/appview/db/star.go @@ -0,0 +1,150 @@ +package db + +import ( + "log" + "time" + + "github.com/bluesky-social/indigo/atproto/syntax" +) + +type Star struct { + StarredByDid string + RepoAt syntax.ATURI + Repo *Repo + Created time.Time + Rkey string +} + +func (star *Star) ResolveRepo(e Execer) error { + if star.Repo != nil { + return nil + } + + repo, err := GetRepoByAtUri(e, star.RepoAt.String()) + if err != nil { + return err + } + + star.Repo = repo + return nil +} + +func AddStar(e Execer, starredByDid string, repoAt syntax.ATURI, rkey string) error { + query := `insert or ignore into stars (starred_by_did, repo_at, rkey) values (?, ?, ?)` + _, err := e.Exec(query, starredByDid, repoAt, rkey) + return err +} + +// Get a star record +func GetStar(e Execer, starredByDid string, repoAt syntax.ATURI) (*Star, error) { + query := ` + select starred_by_did, repo_at, created, rkey + from stars + where starred_by_did = ? and repo_at = ?` + row := e.QueryRow(query, starredByDid, repoAt) + + var star Star + var created string + err := row.Scan(&star.StarredByDid, &star.RepoAt, &created, &star.Rkey) + if err != nil { + return nil, err + } + + createdAtTime, err := time.Parse(time.RFC3339, created) + if err != nil { + log.Println("unable to determine followed at time") + star.Created = time.Now() + } else { + star.Created = createdAtTime + } + + return &star, nil +} + +// Remove a star +func DeleteStar(e Execer, starredByDid string, repoAt syntax.ATURI) error { + _, err := e.Exec(`delete from stars where starred_by_did = ? and repo_at = ?`, starredByDid, repoAt) + return err +} + +func GetStarCount(e Execer, repoAt syntax.ATURI) (int, error) { + stars := 0 + err := e.QueryRow( + `select count(starred_by_did) from stars where repo_at = ?`, repoAt).Scan(&stars) + if err != nil { + return 0, err + } + return stars, nil +} + +func GetStarStatus(e Execer, userDid string, repoAt syntax.ATURI) bool { + if _, err := GetStar(e, userDid, repoAt); err != nil { + return false + } else { + return true + } +} + +func GetAllStars(e Execer, limit int) ([]Star, error) { + var stars []Star + + rows, err := e.Query(` + select + s.starred_by_did, + s.repo_at, + s.rkey, + s.created, + r.did, + r.name, + r.knot, + r.rkey, + r.created, + r.at_uri + from stars s + join repos r on s.repo_at = r.at_uri + `) + + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + var star Star + var repo Repo + var starCreatedAt, repoCreatedAt string + + if err := rows.Scan( + &star.StarredByDid, + &star.RepoAt, + &star.Rkey, + &starCreatedAt, + &repo.Did, + &repo.Name, + &repo.Knot, + &repo.Rkey, + &repoCreatedAt, + &repo.AtUri, + ); err != nil { + return nil, err + } + + star.Created, err = time.Parse(time.RFC3339, starCreatedAt) + if err != nil { + star.Created = time.Now() + } + repo.Created, err = time.Parse(time.RFC3339, repoCreatedAt) + if err != nil { + repo.Created = time.Now() + } + star.Repo = &repo + + stars = append(stars, star) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return stars, nil +} diff --git a/appview/db/timeline.go b/appview/db/timeline.go --- a/appview/db/timeline.go +++ b/appview/db/timeline.go @@ -8,18 +8,27 @@ type TimelineEvent struct { *Repo *Follow + *Star EventAt time.Time } +// TODO: this gathers heterogenous events from different sources and aggregates +// them in code; if we did this entirely in sql, we could order and limit and paginate easily func MakeTimeline(e Execer) ([]TimelineEvent, error) { var events []TimelineEvent + limit := 50 - repos, err := GetAllRepos(e) + repos, err := GetAllRepos(e, limit) + if err != nil { + return nil, err + } + + follows, err := GetAllFollows(e, limit) if err != nil { return nil, err } - follows, err := GetAllFollows(e) + stars, err := GetAllStars(e, limit) if err != nil { return nil, err } @@ -27,26 +36,31 @@ for _, repo := range repos { events = append(events, TimelineEvent{ Repo: &repo, - Follow: nil, EventAt: repo.Created, }) } for _, follow := range follows { events = append(events, TimelineEvent{ - Repo: nil, Follow: &follow, EventAt: follow.FollowedAt, }) } + for _, star := range stars { + events = append(events, TimelineEvent{ + Star: &star, + EventAt: star.Created, + }) + } + sort.Slice(events, func(i, j int) bool { return events[i].EventAt.After(events[j].EventAt) }) // Limit the slice to 100 events - if len(events) > 50 { - events = events[:50] + if len(events) > limit { + events = events[:limit] } return events, nil diff --git a/appview/pages/funcmap.go b/appview/pages/funcmap.go --- a/appview/pages/funcmap.go +++ b/appview/pages/funcmap.go @@ -106,5 +106,12 @@ }, "markdown": func(text string) template.HTML { return template.HTML(renderMarkdown(text)) }, + "isNil": func(t any) bool { + // returns false for other "zero" values + return t == nil + }, + "not": func(t bool) bool { + return !t + }, } } diff --git a/appview/pages/pages.go b/appview/pages/pages.go --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -17,6 +17,7 @@ "github.com/alecthomas/chroma/v2" chromahtml "github.com/alecthomas/chroma/v2/formatters/html" "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" + "github.com/bluesky-social/indigo/atproto/syntax" "github.com/microcosm-cc/bluemonday" "github.com/sotangled/tangled/appview/auth" "github.com/sotangled/tangled/appview/db" @@ -43,11 +44,26 @@ if !d.IsDir() && strings.HasSuffix(path, ".html") { name := strings.TrimPrefix(path, "templates/") name = strings.TrimSuffix(name, ".html") - if !strings.HasPrefix(path, "templates/layouts/") { + // add fragments as templates + if strings.HasPrefix(path, "templates/fragments/") { + tmpl, err := template.New(name). + Funcs(funcMap()). + ParseFS(files, path) + if err != nil { + return fmt.Errorf("setting up fragment: %w", err) + } + + templates[name] = tmpl + log.Printf("loaded fragment: %s", name) + } + + // layouts and fragments are applied first + if !strings.HasPrefix(path, "templates/layouts/") && + !strings.HasPrefix(path, "templates/fragments/") { // Add the page template on top of the base tmpl, err := template.New(name). Funcs(funcMap()). - ParseFS(files, "templates/layouts/*.html", path) + ParseFS(files, "templates/layouts/*.html", "templates/fragments/*.html", path) if err != nil { return fmt.Errorf("setting up template: %w", err) } @@ -159,13 +175,35 @@ func (p *Pages) ProfilePage(w io.Writer, params ProfilePageParams) error { return p.execute("user/profile", w, params) } +type FollowFragmentParams struct { + UserDid string + FollowStatus db.FollowStatus +} + +func (p *Pages) FollowFragment(w io.Writer, params FollowFragmentParams) error { + return p.executePlain("fragments/follow", w, params) +} + +type StarFragmentParams struct { + IsStarred bool + RepoAt syntax.ATURI + Stats db.RepoStats +} + +func (p *Pages) StarFragment(w io.Writer, params StarFragmentParams) error { + return p.executePlain("fragments/star", w, params) +} + type RepoInfo struct { Name string OwnerDid string OwnerHandle string Description string Knot string + RepoAt syntax.ATURI SettingsAllowed bool + IsStarred bool + Stats db.RepoStats } func (r RepoInfo) OwnerWithAt() string { @@ -192,6 +230,23 @@ tabs = append(tabs, []string{"settings", "/settings"}) } return tabs +} + +// each tab on a repo could have some metadata: +// +// issues -> number of open issues etc. +// settings -> a warning icon to setup branch protection? idk +// +// we gather these bits of info here, because go templates +// are difficult to program in +func (r RepoInfo) TabMetadata() map[string]any { + meta := make(map[string]any) + + meta["issues"] = r.Stats.IssueCount.Open + + // more stuff? + + return meta } type RepoIndexParams struct { diff --git a/appview/pages/templates/fragments/follow.html b/appview/pages/templates/fragments/follow.html new file mode 100644 --- /dev/null +++ b/appview/pages/templates/fragments/follow.html @@ -0,0 +1,17 @@ +{{ define "fragments/follow" }} + +{{ end }} diff --git a/appview/pages/templates/fragments/star.html b/appview/pages/templates/fragments/star.html new file mode 100644 --- /dev/null +++ b/appview/pages/templates/fragments/star.html @@ -0,0 +1,36 @@ +{{ define "fragments/star" }} + + +{{ end }} + diff --git a/appview/pages/templates/layouts/repobase.html b/appview/pages/templates/layouts/repobase.html --- a/appview/pages/templates/layouts/repobase.html +++ b/appview/pages/templates/layouts/repobase.html @@ -2,27 +2,32 @@ {{ define "title" }}{{ .RepoInfo.FullName }}{{ end }} {{ define "content" }}
+

- {{ .RepoInfo.OwnerWithAt }} - / - {{ .RepoInfo.Name }} + {{ .RepoInfo.OwnerWithAt }} + / + {{ .RepoInfo.Name }}

- - {{ if .RepoInfo.Description }} - {{ .RepoInfo.Description }} - {{ else }} - this repo has no description - {{ end }} - + {{ template "fragments/star" .RepoInfo }} +
+ + {{ if .RepoInfo.Description }} + {{ .RepoInfo.Description }} + {{ else }} + this repo has no description + {{ end }} +