Monorepo for Tangled tangled.org

add stars to tangled

+693 -529
api/tangled/cbor_gen.go
··· 18 18 var _ = math.E 19 19 var _ = sort.Sort 20 20 21 - func (t *PublicKey) MarshalCBOR(w io.Writer) error { 21 + func (t *FeedStar) MarshalCBOR(w io.Writer) error { 22 22 if t == nil { 23 23 _, err := w.Write(cbg.CborNull) 24 24 return err ··· 26 26 27 27 cw := cbg.NewCborWriter(w) 28 28 29 - if _, err := cw.Write([]byte{164}); err != nil { 29 + if _, err := cw.Write([]byte{163}); err != nil { 30 30 return err 31 31 } 32 32 33 - // t.Key (string) (string) 34 - if len("key") > 1000000 { 35 - return xerrors.Errorf("Value in field \"key\" was too long") 33 + // t.LexiconTypeID (string) (string) 34 + if len("$type") > 1000000 { 35 + return xerrors.Errorf("Value in field \"$type\" was too long") 36 36 } 37 37 38 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("key"))); err != nil { 38 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { 39 39 return err 40 40 } 41 - if _, err := cw.WriteString(string("key")); err != nil { 41 + if _, err := cw.WriteString(string("$type")); err != nil { 42 42 return err 43 43 } 44 44 45 - if len(t.Key) > 1000000 { 46 - return xerrors.Errorf("Value in field t.Key was too long") 47 - } 48 - 49 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Key))); err != nil { 45 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.feed.star"))); err != nil { 50 46 return err 51 47 } 52 - if _, err := cw.WriteString(string(t.Key)); err != nil { 48 + if _, err := cw.WriteString(string("sh.tangled.feed.star")); err != nil { 53 49 return err 54 50 } 55 51 56 - // t.Name (string) (string) 57 - if len("name") > 1000000 { 58 - return xerrors.Errorf("Value in field \"name\" was too long") 52 + // t.Subject (string) (string) 53 + if len("subject") > 1000000 { 54 + return xerrors.Errorf("Value in field \"subject\" was too long") 59 55 } 60 56 61 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("name"))); err != nil { 57 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("subject"))); err != nil { 62 58 return err 63 59 } 64 - if _, err := cw.WriteString(string("name")); err != nil { 60 + if _, err := cw.WriteString(string("subject")); err != nil { 65 61 return err 66 62 } 67 63 68 - if len(t.Name) > 1000000 { 69 - return xerrors.Errorf("Value in field t.Name was too long") 64 + if len(t.Subject) > 1000000 { 65 + return xerrors.Errorf("Value in field t.Subject was too long") 70 66 } 71 67 72 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Name))); err != nil { 68 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Subject))); err != nil { 73 69 return err 74 70 } 75 - if _, err := cw.WriteString(string(t.Name)); err != nil { 71 + if _, err := cw.WriteString(string(t.Subject)); err != nil { 76 72 return err 77 73 } 78 74 79 - // t.LexiconTypeID (string) (string) 80 - if len("$type") > 1000000 { 81 - return xerrors.Errorf("Value in field \"$type\" was too long") 82 - } 83 - 84 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { 85 - return err 86 - } 87 - if _, err := cw.WriteString(string("$type")); err != nil { 88 - return err 89 - } 90 - 91 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.publicKey"))); err != nil { 92 - return err 93 - } 94 - if _, err := cw.WriteString(string("sh.tangled.publicKey")); err != nil { 95 - return err 96 - } 97 - 98 - // t.Created (string) (string) 99 - if len("created") > 1000000 { 100 - return xerrors.Errorf("Value in field \"created\" was too long") 75 + // t.CreatedAt (string) (string) 76 + if len("createdAt") > 1000000 { 77 + return xerrors.Errorf("Value in field \"createdAt\" was too long") 101 78 } 102 79 103 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("created"))); err != nil { 80 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("createdAt"))); err != nil { 104 81 return err 105 82 } 106 - if _, err := cw.WriteString(string("created")); err != nil { 83 + if _, err := cw.WriteString(string("createdAt")); err != nil { 107 84 return err 108 85 } 109 86 110 - if len(t.Created) > 1000000 { 111 - return xerrors.Errorf("Value in field t.Created was too long") 87 + if len(t.CreatedAt) > 1000000 { 88 + return xerrors.Errorf("Value in field t.CreatedAt was too long") 112 89 } 113 90 114 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Created))); err != nil { 91 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.CreatedAt))); err != nil { 115 92 return err 116 93 } 117 - if _, err := cw.WriteString(string(t.Created)); err != nil { 94 + if _, err := cw.WriteString(string(t.CreatedAt)); err != nil { 118 95 return err 119 96 } 120 97 return nil 121 98 } 122 99 123 - func (t *PublicKey) UnmarshalCBOR(r io.Reader) (err error) { 124 - *t = PublicKey{} 100 + func (t *FeedStar) UnmarshalCBOR(r io.Reader) (err error) { 101 + *t = FeedStar{} 125 102 126 103 cr := cbg.NewCborReader(r) 127 104 ··· 140 117 } 141 118 142 119 if extra > cbg.MaxLength { 143 - return fmt.Errorf("PublicKey: map struct too large (%d)", extra) 120 + return fmt.Errorf("FeedStar: map struct too large (%d)", extra) 144 121 } 145 122 146 123 n := extra 147 124 148 - nameBuf := make([]byte, 7) 125 + nameBuf := make([]byte, 9) 149 126 for i := uint64(0); i < n; i++ { 150 127 nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) 151 128 if err != nil { ··· 161 138 } 162 139 163 140 switch string(nameBuf[:nameLen]) { 164 - // t.Key (string) (string) 165 - case "key": 166 - 167 - { 168 - sval, err := cbg.ReadStringWithMax(cr, 1000000) 169 - if err != nil { 170 - return err 171 - } 172 - 173 - t.Key = string(sval) 174 - } 175 - // t.Name (string) (string) 176 - case "name": 141 + // t.LexiconTypeID (string) (string) 142 + case "$type": 177 143 178 144 { 179 145 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 181 147 return err 182 148 } 183 149 184 - t.Name = string(sval) 150 + t.LexiconTypeID = string(sval) 185 151 } 186 - // t.LexiconTypeID (string) (string) 187 - case "$type": 152 + // t.Subject (string) (string) 153 + case "subject": 188 154 189 155 { 190 156 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 192 158 return err 193 159 } 194 160 195 - t.LexiconTypeID = string(sval) 161 + t.Subject = string(sval) 196 162 } 197 - // t.Created (string) (string) 198 - case "created": 163 + // t.CreatedAt (string) (string) 164 + case "createdAt": 199 165 200 166 { 201 167 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 203 169 return err 204 170 } 205 171 206 - t.Created = string(sval) 172 + t.CreatedAt = string(sval) 207 173 } 208 174 209 175 default: ··· 216 182 217 183 return nil 218 184 } 219 - func (t *KnotMember) MarshalCBOR(w io.Writer) error { 185 + func (t *GraphFollow) MarshalCBOR(w io.Writer) error { 220 186 if t == nil { 221 187 _, err := w.Write(cbg.CborNull) 222 188 return err 223 189 } 224 190 225 191 cw := cbg.NewCborWriter(w) 226 - fieldCount := 4 227 192 228 - if t.AddedAt == nil { 229 - fieldCount-- 230 - } 231 - 232 - if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { 193 + if _, err := cw.Write([]byte{163}); err != nil { 233 194 return err 234 195 } 235 196 ··· 245 206 return err 246 207 } 247 208 248 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.knot.member"))); err != nil { 209 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.graph.follow"))); err != nil { 249 210 return err 250 211 } 251 - if _, err := cw.WriteString(string("sh.tangled.knot.member")); err != nil { 212 + if _, err := cw.WriteString(string("sh.tangled.graph.follow")); err != nil { 252 213 return err 253 214 } 254 215 255 - // t.Domain (string) (string) 256 - if len("domain") > 1000000 { 257 - return xerrors.Errorf("Value in field \"domain\" was too long") 216 + // t.Subject (string) (string) 217 + if len("subject") > 1000000 { 218 + return xerrors.Errorf("Value in field \"subject\" was too long") 258 219 } 259 220 260 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("domain"))); err != nil { 221 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("subject"))); err != nil { 261 222 return err 262 223 } 263 - if _, err := cw.WriteString(string("domain")); err != nil { 224 + if _, err := cw.WriteString(string("subject")); err != nil { 264 225 return err 265 226 } 266 227 267 - if len(t.Domain) > 1000000 { 268 - return xerrors.Errorf("Value in field t.Domain was too long") 228 + if len(t.Subject) > 1000000 { 229 + return xerrors.Errorf("Value in field t.Subject was too long") 269 230 } 270 231 271 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Domain))); err != nil { 232 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Subject))); err != nil { 272 233 return err 273 234 } 274 - if _, err := cw.WriteString(string(t.Domain)); err != nil { 235 + if _, err := cw.WriteString(string(t.Subject)); err != nil { 275 236 return err 276 237 } 277 238 278 - // t.Member (string) (string) 279 - if len("member") > 1000000 { 280 - return xerrors.Errorf("Value in field \"member\" was too long") 239 + // t.CreatedAt (string) (string) 240 + if len("createdAt") > 1000000 { 241 + return xerrors.Errorf("Value in field \"createdAt\" was too long") 281 242 } 282 243 283 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("member"))); err != nil { 244 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("createdAt"))); err != nil { 284 245 return err 285 246 } 286 - if _, err := cw.WriteString(string("member")); err != nil { 247 + if _, err := cw.WriteString(string("createdAt")); err != nil { 287 248 return err 288 249 } 289 250 290 - if len(t.Member) > 1000000 { 291 - return xerrors.Errorf("Value in field t.Member was too long") 251 + if len(t.CreatedAt) > 1000000 { 252 + return xerrors.Errorf("Value in field t.CreatedAt was too long") 292 253 } 293 254 294 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Member))); err != nil { 255 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.CreatedAt))); err != nil { 295 256 return err 296 257 } 297 - if _, err := cw.WriteString(string(t.Member)); err != nil { 258 + if _, err := cw.WriteString(string(t.CreatedAt)); err != nil { 298 259 return err 299 260 } 300 - 301 - // t.AddedAt (string) (string) 302 - if t.AddedAt != nil { 303 - 304 - if len("addedAt") > 1000000 { 305 - return xerrors.Errorf("Value in field \"addedAt\" was too long") 306 - } 307 - 308 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { 309 - return err 310 - } 311 - if _, err := cw.WriteString(string("addedAt")); err != nil { 312 - return err 313 - } 314 - 315 - if t.AddedAt == nil { 316 - if _, err := cw.Write(cbg.CborNull); err != nil { 317 - return err 318 - } 319 - } else { 320 - if len(*t.AddedAt) > 1000000 { 321 - return xerrors.Errorf("Value in field t.AddedAt was too long") 322 - } 323 - 324 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AddedAt))); err != nil { 325 - return err 326 - } 327 - if _, err := cw.WriteString(string(*t.AddedAt)); err != nil { 328 - return err 329 - } 330 - } 331 - } 332 261 return nil 333 262 } 334 263 335 - func (t *KnotMember) UnmarshalCBOR(r io.Reader) (err error) { 336 - *t = KnotMember{} 264 + func (t *GraphFollow) UnmarshalCBOR(r io.Reader) (err error) { 265 + *t = GraphFollow{} 337 266 338 267 cr := cbg.NewCborReader(r) 339 268 ··· 352 281 } 353 282 354 283 if extra > cbg.MaxLength { 355 - return fmt.Errorf("KnotMember: map struct too large (%d)", extra) 284 + return fmt.Errorf("GraphFollow: map struct too large (%d)", extra) 356 285 } 357 286 358 287 n := extra 359 288 360 - nameBuf := make([]byte, 7) 289 + nameBuf := make([]byte, 9) 361 290 for i := uint64(0); i < n; i++ { 362 291 nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) 363 292 if err != nil { ··· 384 313 385 314 t.LexiconTypeID = string(sval) 386 315 } 387 - // t.Domain (string) (string) 388 - case "domain": 316 + // t.Subject (string) (string) 317 + case "subject": 389 318 390 319 { 391 320 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 393 322 return err 394 323 } 395 324 396 - t.Domain = string(sval) 325 + t.Subject = string(sval) 397 326 } 398 - // t.Member (string) (string) 399 - case "member": 327 + // t.CreatedAt (string) (string) 328 + case "createdAt": 400 329 401 330 { 402 331 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 404 333 return err 405 334 } 406 335 407 - t.Member = string(sval) 408 - } 409 - // t.AddedAt (string) (string) 410 - case "addedAt": 411 - 412 - { 413 - b, err := cr.ReadByte() 414 - if err != nil { 415 - return err 416 - } 417 - if b != cbg.CborNull[0] { 418 - if err := cr.UnreadByte(); err != nil { 419 - return err 420 - } 421 - 422 - sval, err := cbg.ReadStringWithMax(cr, 1000000) 423 - if err != nil { 424 - return err 425 - } 426 - 427 - t.AddedAt = (*string)(&sval) 428 - } 336 + t.CreatedAt = string(sval) 429 337 } 430 338 431 339 default: ··· 438 346 439 347 return nil 440 348 } 441 - func (t *GraphFollow) MarshalCBOR(w io.Writer) error { 349 + func (t *KnotMember) MarshalCBOR(w io.Writer) error { 442 350 if t == nil { 443 351 _, err := w.Write(cbg.CborNull) 444 352 return err 445 353 } 446 354 447 355 cw := cbg.NewCborWriter(w) 356 + fieldCount := 4 448 357 449 - if _, err := cw.Write([]byte{163}); err != nil { 358 + if t.AddedAt == nil { 359 + fieldCount-- 360 + } 361 + 362 + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { 450 363 return err 451 364 } 452 365 ··· 462 375 return err 463 376 } 464 377 465 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.graph.follow"))); err != nil { 378 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.knot.member"))); err != nil { 466 379 return err 467 380 } 468 - if _, err := cw.WriteString(string("sh.tangled.graph.follow")); err != nil { 381 + if _, err := cw.WriteString(string("sh.tangled.knot.member")); err != nil { 469 382 return err 470 383 } 471 384 472 - // t.Subject (string) (string) 473 - if len("subject") > 1000000 { 474 - return xerrors.Errorf("Value in field \"subject\" was too long") 385 + // t.Domain (string) (string) 386 + if len("domain") > 1000000 { 387 + return xerrors.Errorf("Value in field \"domain\" was too long") 475 388 } 476 389 477 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("subject"))); err != nil { 390 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("domain"))); err != nil { 478 391 return err 479 392 } 480 - if _, err := cw.WriteString(string("subject")); err != nil { 393 + if _, err := cw.WriteString(string("domain")); err != nil { 481 394 return err 482 395 } 483 396 484 - if len(t.Subject) > 1000000 { 485 - return xerrors.Errorf("Value in field t.Subject was too long") 397 + if len(t.Domain) > 1000000 { 398 + return xerrors.Errorf("Value in field t.Domain was too long") 486 399 } 487 400 488 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Subject))); err != nil { 401 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Domain))); err != nil { 489 402 return err 490 403 } 491 - if _, err := cw.WriteString(string(t.Subject)); err != nil { 404 + if _, err := cw.WriteString(string(t.Domain)); err != nil { 492 405 return err 493 406 } 494 407 495 - // t.CreatedAt (string) (string) 496 - if len("createdAt") > 1000000 { 497 - return xerrors.Errorf("Value in field \"createdAt\" was too long") 408 + // t.Member (string) (string) 409 + if len("member") > 1000000 { 410 + return xerrors.Errorf("Value in field \"member\" was too long") 498 411 } 499 412 500 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("createdAt"))); err != nil { 413 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("member"))); err != nil { 501 414 return err 502 415 } 503 - if _, err := cw.WriteString(string("createdAt")); err != nil { 416 + if _, err := cw.WriteString(string("member")); err != nil { 504 417 return err 505 418 } 506 419 507 - if len(t.CreatedAt) > 1000000 { 508 - return xerrors.Errorf("Value in field t.CreatedAt was too long") 420 + if len(t.Member) > 1000000 { 421 + return xerrors.Errorf("Value in field t.Member was too long") 509 422 } 510 423 511 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.CreatedAt))); err != nil { 424 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Member))); err != nil { 512 425 return err 513 426 } 514 - if _, err := cw.WriteString(string(t.CreatedAt)); err != nil { 427 + if _, err := cw.WriteString(string(t.Member)); err != nil { 515 428 return err 516 429 } 430 + 431 + // t.AddedAt (string) (string) 432 + if t.AddedAt != nil { 433 + 434 + if len("addedAt") > 1000000 { 435 + return xerrors.Errorf("Value in field \"addedAt\" was too long") 436 + } 437 + 438 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { 439 + return err 440 + } 441 + if _, err := cw.WriteString(string("addedAt")); err != nil { 442 + return err 443 + } 444 + 445 + if t.AddedAt == nil { 446 + if _, err := cw.Write(cbg.CborNull); err != nil { 447 + return err 448 + } 449 + } else { 450 + if len(*t.AddedAt) > 1000000 { 451 + return xerrors.Errorf("Value in field t.AddedAt was too long") 452 + } 453 + 454 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AddedAt))); err != nil { 455 + return err 456 + } 457 + if _, err := cw.WriteString(string(*t.AddedAt)); err != nil { 458 + return err 459 + } 460 + } 461 + } 517 462 return nil 518 463 } 519 464 520 - func (t *GraphFollow) UnmarshalCBOR(r io.Reader) (err error) { 521 - *t = GraphFollow{} 465 + func (t *KnotMember) UnmarshalCBOR(r io.Reader) (err error) { 466 + *t = KnotMember{} 522 467 523 468 cr := cbg.NewCborReader(r) 524 469 ··· 537 482 } 538 483 539 484 if extra > cbg.MaxLength { 540 - return fmt.Errorf("GraphFollow: map struct too large (%d)", extra) 485 + return fmt.Errorf("KnotMember: map struct too large (%d)", extra) 541 486 } 542 487 543 488 n := extra 544 489 545 - nameBuf := make([]byte, 9) 490 + nameBuf := make([]byte, 7) 546 491 for i := uint64(0); i < n; i++ { 547 492 nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) 548 493 if err != nil { ··· 569 514 570 515 t.LexiconTypeID = string(sval) 571 516 } 572 - // t.Subject (string) (string) 573 - case "subject": 517 + // t.Domain (string) (string) 518 + case "domain": 574 519 575 520 { 576 521 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 578 523 return err 579 524 } 580 525 581 - t.Subject = string(sval) 526 + t.Domain = string(sval) 582 527 } 583 - // t.CreatedAt (string) (string) 584 - case "createdAt": 528 + // t.Member (string) (string) 529 + case "member": 585 530 586 531 { 587 532 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 589 534 return err 590 535 } 591 536 592 - t.CreatedAt = string(sval) 537 + t.Member = string(sval) 538 + } 539 + // t.AddedAt (string) (string) 540 + case "addedAt": 541 + 542 + { 543 + b, err := cr.ReadByte() 544 + if err != nil { 545 + return err 546 + } 547 + if b != cbg.CborNull[0] { 548 + if err := cr.UnreadByte(); err != nil { 549 + return err 550 + } 551 + 552 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 553 + if err != nil { 554 + return err 555 + } 556 + 557 + t.AddedAt = (*string)(&sval) 558 + } 593 559 } 594 560 595 561 default: ··· 602 568 603 569 return nil 604 570 } 605 - func (t *Repo) MarshalCBOR(w io.Writer) error { 571 + func (t *PublicKey) MarshalCBOR(w io.Writer) error { 606 572 if t == nil { 607 573 _, err := w.Write(cbg.CborNull) 608 574 return err 609 575 } 610 576 611 577 cw := cbg.NewCborWriter(w) 612 - fieldCount := 5 613 578 614 - if t.AddedAt == nil { 615 - fieldCount-- 616 - } 617 - 618 - if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { 579 + if _, err := cw.Write([]byte{164}); err != nil { 619 580 return err 620 581 } 621 582 622 - // t.Knot (string) (string) 623 - if len("knot") > 1000000 { 624 - return xerrors.Errorf("Value in field \"knot\" was too long") 583 + // t.Key (string) (string) 584 + if len("key") > 1000000 { 585 + return xerrors.Errorf("Value in field \"key\" was too long") 625 586 } 626 587 627 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("knot"))); err != nil { 588 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("key"))); err != nil { 628 589 return err 629 590 } 630 - if _, err := cw.WriteString(string("knot")); err != nil { 591 + if _, err := cw.WriteString(string("key")); err != nil { 631 592 return err 632 593 } 633 594 634 - if len(t.Knot) > 1000000 { 635 - return xerrors.Errorf("Value in field t.Knot was too long") 595 + if len(t.Key) > 1000000 { 596 + return xerrors.Errorf("Value in field t.Key was too long") 636 597 } 637 598 638 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Knot))); err != nil { 599 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Key))); err != nil { 639 600 return err 640 601 } 641 - if _, err := cw.WriteString(string(t.Knot)); err != nil { 602 + if _, err := cw.WriteString(string(t.Key)); err != nil { 642 603 return err 643 604 } 644 605 ··· 677 638 return err 678 639 } 679 640 680 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo"))); err != nil { 641 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.publicKey"))); err != nil { 681 642 return err 682 643 } 683 - if _, err := cw.WriteString(string("sh.tangled.repo")); err != nil { 644 + if _, err := cw.WriteString(string("sh.tangled.publicKey")); err != nil { 684 645 return err 685 646 } 686 647 687 - // t.Owner (string) (string) 688 - if len("owner") > 1000000 { 689 - return xerrors.Errorf("Value in field \"owner\" was too long") 648 + // t.Created (string) (string) 649 + if len("created") > 1000000 { 650 + return xerrors.Errorf("Value in field \"created\" was too long") 690 651 } 691 652 692 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { 653 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("created"))); err != nil { 693 654 return err 694 655 } 695 - if _, err := cw.WriteString(string("owner")); err != nil { 656 + if _, err := cw.WriteString(string("created")); err != nil { 696 657 return err 697 658 } 698 659 699 - if len(t.Owner) > 1000000 { 700 - return xerrors.Errorf("Value in field t.Owner was too long") 660 + if len(t.Created) > 1000000 { 661 + return xerrors.Errorf("Value in field t.Created was too long") 701 662 } 702 663 703 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil { 664 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Created))); err != nil { 704 665 return err 705 666 } 706 - if _, err := cw.WriteString(string(t.Owner)); err != nil { 667 + if _, err := cw.WriteString(string(t.Created)); err != nil { 707 668 return err 708 669 } 709 - 710 - // t.AddedAt (string) (string) 711 - if t.AddedAt != nil { 712 - 713 - if len("addedAt") > 1000000 { 714 - return xerrors.Errorf("Value in field \"addedAt\" was too long") 715 - } 716 - 717 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { 718 - return err 719 - } 720 - if _, err := cw.WriteString(string("addedAt")); err != nil { 721 - return err 722 - } 723 - 724 - if t.AddedAt == nil { 725 - if _, err := cw.Write(cbg.CborNull); err != nil { 726 - return err 727 - } 728 - } else { 729 - if len(*t.AddedAt) > 1000000 { 730 - return xerrors.Errorf("Value in field t.AddedAt was too long") 731 - } 732 - 733 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AddedAt))); err != nil { 734 - return err 735 - } 736 - if _, err := cw.WriteString(string(*t.AddedAt)); err != nil { 737 - return err 738 - } 739 - } 740 - } 741 670 return nil 742 671 } 743 672 744 - func (t *Repo) UnmarshalCBOR(r io.Reader) (err error) { 745 - *t = Repo{} 673 + func (t *PublicKey) UnmarshalCBOR(r io.Reader) (err error) { 674 + *t = PublicKey{} 746 675 747 676 cr := cbg.NewCborReader(r) 748 677 ··· 761 690 } 762 691 763 692 if extra > cbg.MaxLength { 764 - return fmt.Errorf("Repo: map struct too large (%d)", extra) 693 + return fmt.Errorf("PublicKey: map struct too large (%d)", extra) 765 694 } 766 695 767 696 n := extra ··· 782 711 } 783 712 784 713 switch string(nameBuf[:nameLen]) { 785 - // t.Knot (string) (string) 786 - case "knot": 714 + // t.Key (string) (string) 715 + case "key": 787 716 788 717 { 789 718 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 791 720 return err 792 721 } 793 722 794 - t.Knot = string(sval) 723 + t.Key = string(sval) 795 724 } 796 725 // t.Name (string) (string) 797 726 case "name": ··· 815 744 816 745 t.LexiconTypeID = string(sval) 817 746 } 818 - // t.Owner (string) (string) 819 - case "owner": 747 + // t.Created (string) (string) 748 + case "created": 820 749 821 750 { 822 751 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 824 753 return err 825 754 } 826 755 827 - t.Owner = string(sval) 828 - } 829 - // t.AddedAt (string) (string) 830 - case "addedAt": 831 - 832 - { 833 - b, err := cr.ReadByte() 834 - if err != nil { 835 - return err 836 - } 837 - if b != cbg.CborNull[0] { 838 - if err := cr.UnreadByte(); err != nil { 839 - return err 840 - } 841 - 842 - sval, err := cbg.ReadStringWithMax(cr, 1000000) 843 - if err != nil { 844 - return err 845 - } 846 - 847 - t.AddedAt = (*string)(&sval) 848 - } 756 + t.Created = string(sval) 849 757 } 850 758 851 759 default: ··· 858 766 859 767 return nil 860 768 } 861 - func (t *RepoIssue) MarshalCBOR(w io.Writer) error { 769 + func (t *RepoIssueComment) MarshalCBOR(w io.Writer) error { 862 770 if t == nil { 863 771 _, err := w.Write(cbg.CborNull) 864 772 return err ··· 871 779 fieldCount-- 872 780 } 873 781 782 + if t.CommentId == nil { 783 + fieldCount-- 784 + } 785 + 874 786 if t.CreatedAt == nil { 787 + fieldCount-- 788 + } 789 + 790 + if t.Owner == nil { 791 + fieldCount-- 792 + } 793 + 794 + if t.Repo == nil { 875 795 fieldCount-- 876 796 } 877 797 ··· 912 832 } 913 833 914 834 // t.Repo (string) (string) 915 - if len("repo") > 1000000 { 916 - return xerrors.Errorf("Value in field \"repo\" was too long") 917 - } 835 + if t.Repo != nil { 918 836 919 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("repo"))); err != nil { 920 - return err 921 - } 922 - if _, err := cw.WriteString(string("repo")); err != nil { 923 - return err 924 - } 837 + if len("repo") > 1000000 { 838 + return xerrors.Errorf("Value in field \"repo\" was too long") 839 + } 925 840 926 - if len(t.Repo) > 1000000 { 927 - return xerrors.Errorf("Value in field t.Repo was too long") 928 - } 841 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("repo"))); err != nil { 842 + return err 843 + } 844 + if _, err := cw.WriteString(string("repo")); err != nil { 845 + return err 846 + } 929 847 930 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Repo))); err != nil { 931 - return err 932 - } 933 - if _, err := cw.WriteString(string(t.Repo)); err != nil { 934 - return err 848 + if t.Repo == nil { 849 + if _, err := cw.Write(cbg.CborNull); err != nil { 850 + return err 851 + } 852 + } else { 853 + if len(*t.Repo) > 1000000 { 854 + return xerrors.Errorf("Value in field t.Repo was too long") 855 + } 856 + 857 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Repo))); err != nil { 858 + return err 859 + } 860 + if _, err := cw.WriteString(string(*t.Repo)); err != nil { 861 + return err 862 + } 863 + } 935 864 } 936 865 937 866 // t.LexiconTypeID (string) (string) ··· 946 875 return err 947 876 } 948 877 949 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo.issue"))); err != nil { 878 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo.issue.comment"))); err != nil { 950 879 return err 951 880 } 952 - if _, err := cw.WriteString(string("sh.tangled.repo.issue")); err != nil { 881 + if _, err := cw.WriteString(string("sh.tangled.repo.issue.comment")); err != nil { 953 882 return err 954 883 } 955 884 956 - // t.Owner (string) (string) 957 - if len("owner") > 1000000 { 958 - return xerrors.Errorf("Value in field \"owner\" was too long") 885 + // t.Issue (string) (string) 886 + if len("issue") > 1000000 { 887 + return xerrors.Errorf("Value in field \"issue\" was too long") 959 888 } 960 889 961 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { 890 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issue"))); err != nil { 962 891 return err 963 892 } 964 - if _, err := cw.WriteString(string("owner")); err != nil { 893 + if _, err := cw.WriteString(string("issue")); err != nil { 965 894 return err 966 895 } 967 896 968 - if len(t.Owner) > 1000000 { 969 - return xerrors.Errorf("Value in field t.Owner was too long") 897 + if len(t.Issue) > 1000000 { 898 + return xerrors.Errorf("Value in field t.Issue was too long") 970 899 } 971 900 972 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil { 901 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Issue))); err != nil { 973 902 return err 974 903 } 975 - if _, err := cw.WriteString(string(t.Owner)); err != nil { 904 + if _, err := cw.WriteString(string(t.Issue)); err != nil { 976 905 return err 977 906 } 978 907 979 - // t.Title (string) (string) 980 - if len("title") > 1000000 { 981 - return xerrors.Errorf("Value in field \"title\" was too long") 982 - } 908 + // t.Owner (string) (string) 909 + if t.Owner != nil { 983 910 984 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("title"))); err != nil { 985 - return err 986 - } 987 - if _, err := cw.WriteString(string("title")); err != nil { 988 - return err 989 - } 911 + if len("owner") > 1000000 { 912 + return xerrors.Errorf("Value in field \"owner\" was too long") 913 + } 990 914 991 - if len(t.Title) > 1000000 { 992 - return xerrors.Errorf("Value in field t.Title was too long") 993 - } 915 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { 916 + return err 917 + } 918 + if _, err := cw.WriteString(string("owner")); err != nil { 919 + return err 920 + } 994 921 995 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Title))); err != nil { 996 - return err 997 - } 998 - if _, err := cw.WriteString(string(t.Title)); err != nil { 999 - return err 1000 - } 922 + if t.Owner == nil { 923 + if _, err := cw.Write(cbg.CborNull); err != nil { 924 + return err 925 + } 926 + } else { 927 + if len(*t.Owner) > 1000000 { 928 + return xerrors.Errorf("Value in field t.Owner was too long") 929 + } 1001 930 1002 - // t.IssueId (int64) (int64) 1003 - if len("issueId") > 1000000 { 1004 - return xerrors.Errorf("Value in field \"issueId\" was too long") 931 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Owner))); err != nil { 932 + return err 933 + } 934 + if _, err := cw.WriteString(string(*t.Owner)); err != nil { 935 + return err 936 + } 937 + } 1005 938 } 1006 939 1007 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issueId"))); err != nil { 1008 - return err 1009 - } 1010 - if _, err := cw.WriteString(string("issueId")); err != nil { 1011 - return err 1012 - } 940 + // t.CommentId (int64) (int64) 941 + if t.CommentId != nil { 1013 942 1014 - if t.IssueId >= 0 { 1015 - if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.IssueId)); err != nil { 943 + if len("commentId") > 1000000 { 944 + return xerrors.Errorf("Value in field \"commentId\" was too long") 945 + } 946 + 947 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("commentId"))); err != nil { 1016 948 return err 1017 949 } 1018 - } else { 1019 - if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.IssueId-1)); err != nil { 950 + if _, err := cw.WriteString(string("commentId")); err != nil { 1020 951 return err 1021 952 } 953 + 954 + if t.CommentId == nil { 955 + if _, err := cw.Write(cbg.CborNull); err != nil { 956 + return err 957 + } 958 + } else { 959 + if *t.CommentId >= 0 { 960 + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.CommentId)); err != nil { 961 + return err 962 + } 963 + } else { 964 + if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-*t.CommentId-1)); err != nil { 965 + return err 966 + } 967 + } 968 + } 969 + 1022 970 } 1023 971 1024 972 // t.CreatedAt (string) (string) ··· 1055 1003 return nil 1056 1004 } 1057 1005 1058 - func (t *RepoIssue) UnmarshalCBOR(r io.Reader) (err error) { 1059 - *t = RepoIssue{} 1006 + func (t *RepoIssueComment) UnmarshalCBOR(r io.Reader) (err error) { 1007 + *t = RepoIssueComment{} 1060 1008 1061 1009 cr := cbg.NewCborReader(r) 1062 1010 ··· 1075 1023 } 1076 1024 1077 1025 if extra > cbg.MaxLength { 1078 - return fmt.Errorf("RepoIssue: map struct too large (%d)", extra) 1026 + return fmt.Errorf("RepoIssueComment: map struct too large (%d)", extra) 1079 1027 } 1080 1028 1081 1029 n := extra ··· 1121 1069 case "repo": 1122 1070 1123 1071 { 1124 - sval, err := cbg.ReadStringWithMax(cr, 1000000) 1072 + b, err := cr.ReadByte() 1125 1073 if err != nil { 1126 1074 return err 1127 1075 } 1076 + if b != cbg.CborNull[0] { 1077 + if err := cr.UnreadByte(); err != nil { 1078 + return err 1079 + } 1128 1080 1129 - t.Repo = string(sval) 1081 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 1082 + if err != nil { 1083 + return err 1084 + } 1085 + 1086 + t.Repo = (*string)(&sval) 1087 + } 1130 1088 } 1131 1089 // t.LexiconTypeID (string) (string) 1132 1090 case "$type": ··· 1139 1097 1140 1098 t.LexiconTypeID = string(sval) 1141 1099 } 1142 - // t.Owner (string) (string) 1143 - case "owner": 1100 + // t.Issue (string) (string) 1101 + case "issue": 1144 1102 1145 1103 { 1146 1104 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 1148 1106 return err 1149 1107 } 1150 1108 1151 - t.Owner = string(sval) 1109 + t.Issue = string(sval) 1152 1110 } 1153 - // t.Title (string) (string) 1154 - case "title": 1111 + // t.Owner (string) (string) 1112 + case "owner": 1155 1113 1156 1114 { 1157 - sval, err := cbg.ReadStringWithMax(cr, 1000000) 1115 + b, err := cr.ReadByte() 1158 1116 if err != nil { 1159 1117 return err 1160 1118 } 1119 + if b != cbg.CborNull[0] { 1120 + if err := cr.UnreadByte(); err != nil { 1121 + return err 1122 + } 1161 1123 1162 - t.Title = string(sval) 1124 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 1125 + if err != nil { 1126 + return err 1127 + } 1128 + 1129 + t.Owner = (*string)(&sval) 1130 + } 1163 1131 } 1164 - // t.IssueId (int64) (int64) 1165 - case "issueId": 1132 + // t.CommentId (int64) (int64) 1133 + case "commentId": 1166 1134 { 1167 - maj, extra, err := cr.ReadHeader() 1135 + 1136 + b, err := cr.ReadByte() 1168 1137 if err != nil { 1169 1138 return err 1170 1139 } 1171 - var extraI int64 1172 - switch maj { 1173 - case cbg.MajUnsignedInt: 1174 - extraI = int64(extra) 1175 - if extraI < 0 { 1176 - return fmt.Errorf("int64 positive overflow") 1140 + if b != cbg.CborNull[0] { 1141 + if err := cr.UnreadByte(); err != nil { 1142 + return err 1177 1143 } 1178 - case cbg.MajNegativeInt: 1179 - extraI = int64(extra) 1180 - if extraI < 0 { 1181 - return fmt.Errorf("int64 negative overflow") 1144 + maj, extra, err := cr.ReadHeader() 1145 + if err != nil { 1146 + return err 1182 1147 } 1183 - extraI = -1 - extraI 1184 - default: 1185 - return fmt.Errorf("wrong type for int64 field: %d", maj) 1186 - } 1148 + var extraI int64 1149 + switch maj { 1150 + case cbg.MajUnsignedInt: 1151 + extraI = int64(extra) 1152 + if extraI < 0 { 1153 + return fmt.Errorf("int64 positive overflow") 1154 + } 1155 + case cbg.MajNegativeInt: 1156 + extraI = int64(extra) 1157 + if extraI < 0 { 1158 + return fmt.Errorf("int64 negative overflow") 1159 + } 1160 + extraI = -1 - extraI 1161 + default: 1162 + return fmt.Errorf("wrong type for int64 field: %d", maj) 1163 + } 1187 1164 1188 - t.IssueId = int64(extraI) 1165 + t.CommentId = (*int64)(&extraI) 1166 + } 1189 1167 } 1190 1168 // t.CreatedAt (string) (string) 1191 1169 case "createdAt": ··· 1407 1385 1408 1386 return nil 1409 1387 } 1410 - func (t *RepoIssueComment) MarshalCBOR(w io.Writer) error { 1388 + func (t *RepoIssue) MarshalCBOR(w io.Writer) error { 1411 1389 if t == nil { 1412 1390 _, err := w.Write(cbg.CborNull) 1413 1391 return err ··· 1420 1398 fieldCount-- 1421 1399 } 1422 1400 1423 - if t.CommentId == nil { 1424 - fieldCount-- 1425 - } 1426 - 1427 1401 if t.CreatedAt == nil { 1428 - fieldCount-- 1429 - } 1430 - 1431 - if t.Owner == nil { 1432 - fieldCount-- 1433 - } 1434 - 1435 - if t.Repo == nil { 1436 1402 fieldCount-- 1437 1403 } 1438 1404 ··· 1473 1439 } 1474 1440 1475 1441 // t.Repo (string) (string) 1476 - if t.Repo != nil { 1477 - 1478 - if len("repo") > 1000000 { 1479 - return xerrors.Errorf("Value in field \"repo\" was too long") 1480 - } 1442 + if len("repo") > 1000000 { 1443 + return xerrors.Errorf("Value in field \"repo\" was too long") 1444 + } 1481 1445 1482 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("repo"))); err != nil { 1483 - return err 1484 - } 1485 - if _, err := cw.WriteString(string("repo")); err != nil { 1486 - return err 1487 - } 1446 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("repo"))); err != nil { 1447 + return err 1448 + } 1449 + if _, err := cw.WriteString(string("repo")); err != nil { 1450 + return err 1451 + } 1488 1452 1489 - if t.Repo == nil { 1490 - if _, err := cw.Write(cbg.CborNull); err != nil { 1491 - return err 1492 - } 1493 - } else { 1494 - if len(*t.Repo) > 1000000 { 1495 - return xerrors.Errorf("Value in field t.Repo was too long") 1496 - } 1453 + if len(t.Repo) > 1000000 { 1454 + return xerrors.Errorf("Value in field t.Repo was too long") 1455 + } 1497 1456 1498 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Repo))); err != nil { 1499 - return err 1500 - } 1501 - if _, err := cw.WriteString(string(*t.Repo)); err != nil { 1502 - return err 1503 - } 1504 - } 1457 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Repo))); err != nil { 1458 + return err 1459 + } 1460 + if _, err := cw.WriteString(string(t.Repo)); err != nil { 1461 + return err 1505 1462 } 1506 1463 1507 1464 // t.LexiconTypeID (string) (string) ··· 1516 1473 return err 1517 1474 } 1518 1475 1519 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo.issue.comment"))); err != nil { 1476 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo.issue"))); err != nil { 1520 1477 return err 1521 1478 } 1522 - if _, err := cw.WriteString(string("sh.tangled.repo.issue.comment")); err != nil { 1479 + if _, err := cw.WriteString(string("sh.tangled.repo.issue")); err != nil { 1523 1480 return err 1524 1481 } 1525 1482 1526 - // t.Issue (string) (string) 1527 - if len("issue") > 1000000 { 1528 - return xerrors.Errorf("Value in field \"issue\" was too long") 1483 + // t.Owner (string) (string) 1484 + if len("owner") > 1000000 { 1485 + return xerrors.Errorf("Value in field \"owner\" was too long") 1529 1486 } 1530 1487 1531 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issue"))); err != nil { 1488 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { 1532 1489 return err 1533 1490 } 1534 - if _, err := cw.WriteString(string("issue")); err != nil { 1491 + if _, err := cw.WriteString(string("owner")); err != nil { 1535 1492 return err 1536 1493 } 1537 1494 1538 - if len(t.Issue) > 1000000 { 1539 - return xerrors.Errorf("Value in field t.Issue was too long") 1495 + if len(t.Owner) > 1000000 { 1496 + return xerrors.Errorf("Value in field t.Owner was too long") 1540 1497 } 1541 1498 1542 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Issue))); err != nil { 1499 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil { 1543 1500 return err 1544 1501 } 1545 - if _, err := cw.WriteString(string(t.Issue)); err != nil { 1502 + if _, err := cw.WriteString(string(t.Owner)); err != nil { 1546 1503 return err 1547 1504 } 1548 1505 1549 - // t.Owner (string) (string) 1550 - if t.Owner != nil { 1506 + // t.Title (string) (string) 1507 + if len("title") > 1000000 { 1508 + return xerrors.Errorf("Value in field \"title\" was too long") 1509 + } 1551 1510 1552 - if len("owner") > 1000000 { 1553 - return xerrors.Errorf("Value in field \"owner\" was too long") 1554 - } 1511 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("title"))); err != nil { 1512 + return err 1513 + } 1514 + if _, err := cw.WriteString(string("title")); err != nil { 1515 + return err 1516 + } 1555 1517 1556 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { 1557 - return err 1558 - } 1559 - if _, err := cw.WriteString(string("owner")); err != nil { 1560 - return err 1561 - } 1518 + if len(t.Title) > 1000000 { 1519 + return xerrors.Errorf("Value in field t.Title was too long") 1520 + } 1562 1521 1563 - if t.Owner == nil { 1564 - if _, err := cw.Write(cbg.CborNull); err != nil { 1565 - return err 1566 - } 1567 - } else { 1568 - if len(*t.Owner) > 1000000 { 1569 - return xerrors.Errorf("Value in field t.Owner was too long") 1570 - } 1522 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Title))); err != nil { 1523 + return err 1524 + } 1525 + if _, err := cw.WriteString(string(t.Title)); err != nil { 1526 + return err 1527 + } 1571 1528 1572 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Owner))); err != nil { 1573 - return err 1574 - } 1575 - if _, err := cw.WriteString(string(*t.Owner)); err != nil { 1576 - return err 1577 - } 1578 - } 1529 + // t.IssueId (int64) (int64) 1530 + if len("issueId") > 1000000 { 1531 + return xerrors.Errorf("Value in field \"issueId\" was too long") 1579 1532 } 1580 1533 1581 - // t.CommentId (int64) (int64) 1582 - if t.CommentId != nil { 1583 - 1584 - if len("commentId") > 1000000 { 1585 - return xerrors.Errorf("Value in field \"commentId\" was too long") 1586 - } 1534 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("issueId"))); err != nil { 1535 + return err 1536 + } 1537 + if _, err := cw.WriteString(string("issueId")); err != nil { 1538 + return err 1539 + } 1587 1540 1588 - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("commentId"))); err != nil { 1541 + if t.IssueId >= 0 { 1542 + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.IssueId)); err != nil { 1589 1543 return err 1590 1544 } 1591 - if _, err := cw.WriteString(string("commentId")); err != nil { 1545 + } else { 1546 + if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.IssueId-1)); err != nil { 1592 1547 return err 1593 1548 } 1594 - 1595 - if t.CommentId == nil { 1596 - if _, err := cw.Write(cbg.CborNull); err != nil { 1597 - return err 1598 - } 1599 - } else { 1600 - if *t.CommentId >= 0 { 1601 - if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(*t.CommentId)); err != nil { 1602 - return err 1603 - } 1604 - } else { 1605 - if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-*t.CommentId-1)); err != nil { 1606 - return err 1607 - } 1608 - } 1609 - } 1610 - 1611 1549 } 1612 1550 1613 1551 // t.CreatedAt (string) (string) ··· 1644 1582 return nil 1645 1583 } 1646 1584 1647 - func (t *RepoIssueComment) UnmarshalCBOR(r io.Reader) (err error) { 1648 - *t = RepoIssueComment{} 1585 + func (t *RepoIssue) UnmarshalCBOR(r io.Reader) (err error) { 1586 + *t = RepoIssue{} 1649 1587 1650 1588 cr := cbg.NewCborReader(r) 1651 1589 ··· 1664 1602 } 1665 1603 1666 1604 if extra > cbg.MaxLength { 1667 - return fmt.Errorf("RepoIssueComment: map struct too large (%d)", extra) 1605 + return fmt.Errorf("RepoIssue: map struct too large (%d)", extra) 1668 1606 } 1669 1607 1670 1608 n := extra ··· 1710 1648 case "repo": 1711 1649 1712 1650 { 1713 - b, err := cr.ReadByte() 1651 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 1714 1652 if err != nil { 1715 1653 return err 1716 1654 } 1717 - if b != cbg.CborNull[0] { 1718 - if err := cr.UnreadByte(); err != nil { 1719 - return err 1720 - } 1721 1655 1722 - sval, err := cbg.ReadStringWithMax(cr, 1000000) 1723 - if err != nil { 1724 - return err 1725 - } 1726 - 1727 - t.Repo = (*string)(&sval) 1728 - } 1656 + t.Repo = string(sval) 1729 1657 } 1730 1658 // t.LexiconTypeID (string) (string) 1731 1659 case "$type": ··· 1738 1666 1739 1667 t.LexiconTypeID = string(sval) 1740 1668 } 1741 - // t.Issue (string) (string) 1742 - case "issue": 1669 + // t.Owner (string) (string) 1670 + case "owner": 1671 + 1672 + { 1673 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 1674 + if err != nil { 1675 + return err 1676 + } 1677 + 1678 + t.Owner = string(sval) 1679 + } 1680 + // t.Title (string) (string) 1681 + case "title": 1743 1682 1744 1683 { 1745 1684 sval, err := cbg.ReadStringWithMax(cr, 1000000) ··· 1747 1686 return err 1748 1687 } 1749 1688 1750 - t.Issue = string(sval) 1689 + t.Title = string(sval) 1690 + } 1691 + // t.IssueId (int64) (int64) 1692 + case "issueId": 1693 + { 1694 + maj, extra, err := cr.ReadHeader() 1695 + if err != nil { 1696 + return err 1697 + } 1698 + var extraI int64 1699 + switch maj { 1700 + case cbg.MajUnsignedInt: 1701 + extraI = int64(extra) 1702 + if extraI < 0 { 1703 + return fmt.Errorf("int64 positive overflow") 1704 + } 1705 + case cbg.MajNegativeInt: 1706 + extraI = int64(extra) 1707 + if extraI < 0 { 1708 + return fmt.Errorf("int64 negative overflow") 1709 + } 1710 + extraI = -1 - extraI 1711 + default: 1712 + return fmt.Errorf("wrong type for int64 field: %d", maj) 1713 + } 1714 + 1715 + t.IssueId = int64(extraI) 1751 1716 } 1752 - // t.Owner (string) (string) 1753 - case "owner": 1717 + // t.CreatedAt (string) (string) 1718 + case "createdAt": 1754 1719 1755 1720 { 1756 1721 b, err := cr.ReadByte() ··· 1767 1732 return err 1768 1733 } 1769 1734 1770 - t.Owner = (*string)(&sval) 1735 + t.CreatedAt = (*string)(&sval) 1736 + } 1737 + } 1738 + 1739 + default: 1740 + // Field doesn't exist on this type, so ignore it 1741 + if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil { 1742 + return err 1743 + } 1744 + } 1745 + } 1746 + 1747 + return nil 1748 + } 1749 + func (t *Repo) MarshalCBOR(w io.Writer) error { 1750 + if t == nil { 1751 + _, err := w.Write(cbg.CborNull) 1752 + return err 1753 + } 1754 + 1755 + cw := cbg.NewCborWriter(w) 1756 + fieldCount := 5 1757 + 1758 + if t.AddedAt == nil { 1759 + fieldCount-- 1760 + } 1761 + 1762 + if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil { 1763 + return err 1764 + } 1765 + 1766 + // t.Knot (string) (string) 1767 + if len("knot") > 1000000 { 1768 + return xerrors.Errorf("Value in field \"knot\" was too long") 1769 + } 1770 + 1771 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("knot"))); err != nil { 1772 + return err 1773 + } 1774 + if _, err := cw.WriteString(string("knot")); err != nil { 1775 + return err 1776 + } 1777 + 1778 + if len(t.Knot) > 1000000 { 1779 + return xerrors.Errorf("Value in field t.Knot was too long") 1780 + } 1781 + 1782 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Knot))); err != nil { 1783 + return err 1784 + } 1785 + if _, err := cw.WriteString(string(t.Knot)); err != nil { 1786 + return err 1787 + } 1788 + 1789 + // t.Name (string) (string) 1790 + if len("name") > 1000000 { 1791 + return xerrors.Errorf("Value in field \"name\" was too long") 1792 + } 1793 + 1794 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("name"))); err != nil { 1795 + return err 1796 + } 1797 + if _, err := cw.WriteString(string("name")); err != nil { 1798 + return err 1799 + } 1800 + 1801 + if len(t.Name) > 1000000 { 1802 + return xerrors.Errorf("Value in field t.Name was too long") 1803 + } 1804 + 1805 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Name))); err != nil { 1806 + return err 1807 + } 1808 + if _, err := cw.WriteString(string(t.Name)); err != nil { 1809 + return err 1810 + } 1811 + 1812 + // t.LexiconTypeID (string) (string) 1813 + if len("$type") > 1000000 { 1814 + return xerrors.Errorf("Value in field \"$type\" was too long") 1815 + } 1816 + 1817 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("$type"))); err != nil { 1818 + return err 1819 + } 1820 + if _, err := cw.WriteString(string("$type")); err != nil { 1821 + return err 1822 + } 1823 + 1824 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("sh.tangled.repo"))); err != nil { 1825 + return err 1826 + } 1827 + if _, err := cw.WriteString(string("sh.tangled.repo")); err != nil { 1828 + return err 1829 + } 1830 + 1831 + // t.Owner (string) (string) 1832 + if len("owner") > 1000000 { 1833 + return xerrors.Errorf("Value in field \"owner\" was too long") 1834 + } 1835 + 1836 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("owner"))); err != nil { 1837 + return err 1838 + } 1839 + if _, err := cw.WriteString(string("owner")); err != nil { 1840 + return err 1841 + } 1842 + 1843 + if len(t.Owner) > 1000000 { 1844 + return xerrors.Errorf("Value in field t.Owner was too long") 1845 + } 1846 + 1847 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Owner))); err != nil { 1848 + return err 1849 + } 1850 + if _, err := cw.WriteString(string(t.Owner)); err != nil { 1851 + return err 1852 + } 1853 + 1854 + // t.AddedAt (string) (string) 1855 + if t.AddedAt != nil { 1856 + 1857 + if len("addedAt") > 1000000 { 1858 + return xerrors.Errorf("Value in field \"addedAt\" was too long") 1859 + } 1860 + 1861 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("addedAt"))); err != nil { 1862 + return err 1863 + } 1864 + if _, err := cw.WriteString(string("addedAt")); err != nil { 1865 + return err 1866 + } 1867 + 1868 + if t.AddedAt == nil { 1869 + if _, err := cw.Write(cbg.CborNull); err != nil { 1870 + return err 1871 + } 1872 + } else { 1873 + if len(*t.AddedAt) > 1000000 { 1874 + return xerrors.Errorf("Value in field t.AddedAt was too long") 1875 + } 1876 + 1877 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.AddedAt))); err != nil { 1878 + return err 1879 + } 1880 + if _, err := cw.WriteString(string(*t.AddedAt)); err != nil { 1881 + return err 1882 + } 1883 + } 1884 + } 1885 + return nil 1886 + } 1887 + 1888 + func (t *Repo) UnmarshalCBOR(r io.Reader) (err error) { 1889 + *t = Repo{} 1890 + 1891 + cr := cbg.NewCborReader(r) 1892 + 1893 + maj, extra, err := cr.ReadHeader() 1894 + if err != nil { 1895 + return err 1896 + } 1897 + defer func() { 1898 + if err == io.EOF { 1899 + err = io.ErrUnexpectedEOF 1900 + } 1901 + }() 1902 + 1903 + if maj != cbg.MajMap { 1904 + return fmt.Errorf("cbor input should be of type map") 1905 + } 1906 + 1907 + if extra > cbg.MaxLength { 1908 + return fmt.Errorf("Repo: map struct too large (%d)", extra) 1909 + } 1910 + 1911 + n := extra 1912 + 1913 + nameBuf := make([]byte, 7) 1914 + for i := uint64(0); i < n; i++ { 1915 + nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000) 1916 + if err != nil { 1917 + return err 1918 + } 1919 + 1920 + if !ok { 1921 + // Field doesn't exist on this type, so ignore it 1922 + if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil { 1923 + return err 1924 + } 1925 + continue 1926 + } 1927 + 1928 + switch string(nameBuf[:nameLen]) { 1929 + // t.Knot (string) (string) 1930 + case "knot": 1931 + 1932 + { 1933 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 1934 + if err != nil { 1935 + return err 1771 1936 } 1937 + 1938 + t.Knot = string(sval) 1772 1939 } 1773 - // t.CommentId (int64) (int64) 1774 - case "commentId": 1940 + // t.Name (string) (string) 1941 + case "name": 1942 + 1775 1943 { 1944 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 1945 + if err != nil { 1946 + return err 1947 + } 1776 1948 1777 - b, err := cr.ReadByte() 1949 + t.Name = string(sval) 1950 + } 1951 + // t.LexiconTypeID (string) (string) 1952 + case "$type": 1953 + 1954 + { 1955 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 1778 1956 if err != nil { 1779 1957 return err 1780 1958 } 1781 - if b != cbg.CborNull[0] { 1782 - if err := cr.UnreadByte(); err != nil { 1783 - return err 1784 - } 1785 - maj, extra, err := cr.ReadHeader() 1786 - if err != nil { 1787 - return err 1788 - } 1789 - var extraI int64 1790 - switch maj { 1791 - case cbg.MajUnsignedInt: 1792 - extraI = int64(extra) 1793 - if extraI < 0 { 1794 - return fmt.Errorf("int64 positive overflow") 1795 - } 1796 - case cbg.MajNegativeInt: 1797 - extraI = int64(extra) 1798 - if extraI < 0 { 1799 - return fmt.Errorf("int64 negative overflow") 1800 - } 1801 - extraI = -1 - extraI 1802 - default: 1803 - return fmt.Errorf("wrong type for int64 field: %d", maj) 1804 - } 1805 1959 1806 - t.CommentId = (*int64)(&extraI) 1960 + t.LexiconTypeID = string(sval) 1961 + } 1962 + // t.Owner (string) (string) 1963 + case "owner": 1964 + 1965 + { 1966 + sval, err := cbg.ReadStringWithMax(cr, 1000000) 1967 + if err != nil { 1968 + return err 1807 1969 } 1970 + 1971 + t.Owner = string(sval) 1808 1972 } 1809 - // t.CreatedAt (string) (string) 1810 - case "createdAt": 1973 + // t.AddedAt (string) (string) 1974 + case "addedAt": 1811 1975 1812 1976 { 1813 1977 b, err := cr.ReadByte() ··· 1824 1988 return err 1825 1989 } 1826 1990 1827 - t.CreatedAt = (*string)(&sval) 1991 + t.AddedAt = (*string)(&sval) 1828 1992 } 1829 1993 } 1830 1994
+23
api/tangled/feedstar.go
··· 1 + // Code generated by cmd/lexgen (see Makefile's lexgen); DO NOT EDIT. 2 + 3 + package tangled 4 + 5 + // schema: sh.tangled.feed.star 6 + 7 + import ( 8 + "github.com/bluesky-social/indigo/lex/util" 9 + ) 10 + 11 + const ( 12 + FeedStarNSID = "sh.tangled.feed.star" 13 + ) 14 + 15 + func init() { 16 + util.RegisterType("sh.tangled.feed.star", &FeedStar{}) 17 + } // 18 + // RECORDTYPE: FeedStar 19 + type FeedStar struct { 20 + LexiconTypeID string `json:"$type,const=sh.tangled.feed.star" cborgen:"$type,const=sh.tangled.feed.star"` 21 + CreatedAt string `json:"createdAt" cborgen:"createdAt"` 22 + Subject string `json:"subject" cborgen:"subject"` 23 + }
+10
appview/db/db.go
··· 112 112 next_issue_id integer not null default 1 113 113 ); 114 114 115 + create table if not exists stars ( 116 + id integer primary key autoincrement, 117 + starred_by_did text not null, 118 + repo_at text not null, 119 + rkey text not null, 120 + created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 121 + foreign key (repo_at) references repos(at_uri) on delete cascade, 122 + unique(starred_by_did, repo_at) 123 + ); 124 + 115 125 `) 116 126 if err != nil { 117 127 return nil, err
+11 -6
appview/db/follow.go
··· 9 9 UserDid string 10 10 SubjectDid string 11 11 FollowedAt time.Time 12 - RKey string 12 + Rkey string 13 13 } 14 14 15 15 func AddFollow(e Execer, userDid, subjectDid, rkey string) error { ··· 25 25 26 26 var follow Follow 27 27 var followedAt string 28 - err := row.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.RKey) 28 + err := row.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.Rkey) 29 29 if err != nil { 30 30 return nil, err 31 31 } ··· 41 41 return &follow, nil 42 42 } 43 43 44 - // Get a follow record 44 + // Remove a follow 45 45 func DeleteFollow(e Execer, userDid, subjectDid string) error { 46 46 _, err := e.Exec(`delete from follows where user_did = ? and subject_did = ?`, userDid, subjectDid) 47 47 return err ··· 91 91 } 92 92 } 93 93 94 - func GetAllFollows(e Execer) ([]Follow, error) { 94 + func GetAllFollows(e Execer, limit int) ([]Follow, error) { 95 95 var follows []Follow 96 96 97 - rows, err := e.Query(`select user_did, subject_did, followed_at, rkey from follows`) 97 + rows, err := e.Query(` 98 + select user_did, subject_did, followed_at, rkey 99 + from follows 100 + order by followed_at desc 101 + limit ?`, limit, 102 + ) 98 103 if err != nil { 99 104 return nil, err 100 105 } ··· 103 108 for rows.Next() { 104 109 var follow Follow 105 110 var followedAt string 106 - if err := rows.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.RKey); err != nil { 111 + if err := rows.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.Rkey); err != nil { 107 112 return nil, err 108 113 } 109 114
+37 -12
appview/db/issues.go
··· 3 3 import ( 4 4 "database/sql" 5 5 "time" 6 + 7 + "github.com/bluesky-social/indigo/atproto/syntax" 6 8 ) 7 9 8 10 type Issue struct { 9 - RepoAt string 11 + RepoAt syntax.ATURI 10 12 OwnerDid string 11 13 IssueId int 12 14 IssueAt string ··· 18 20 19 21 type Comment struct { 20 22 OwnerDid string 21 - RepoAt string 23 + RepoAt syntax.ATURI 22 24 CommentAt string 23 25 Issue int 24 26 CommentId int ··· 65 67 return nil 66 68 } 67 69 68 - func SetIssueAt(e Execer, repoAt string, issueId int, issueAt string) error { 70 + func SetIssueAt(e Execer, repoAt syntax.ATURI, issueId int, issueAt string) error { 69 71 _, err := e.Exec(`update issues set issue_at = ? where repo_at = ? and issue_id = ?`, issueAt, repoAt, issueId) 70 72 return err 71 73 } 72 74 73 - func GetIssueAt(e Execer, repoAt string, issueId int) (string, error) { 75 + func GetIssueAt(e Execer, repoAt syntax.ATURI, issueId int) (string, error) { 74 76 var issueAt string 75 77 err := e.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt) 76 78 return issueAt, err 77 79 } 78 80 79 - func GetIssueId(e Execer, repoAt string) (int, error) { 81 + func GetIssueId(e Execer, repoAt syntax.ATURI) (int, error) { 80 82 var issueId int 81 83 err := e.QueryRow(`select next_issue_id from repo_issue_seqs where repo_at = ?`, repoAt).Scan(&issueId) 82 84 return issueId - 1, err 83 85 } 84 86 85 - func GetIssueOwnerDid(e Execer, repoAt string, issueId int) (string, error) { 87 + func GetIssueOwnerDid(e Execer, repoAt syntax.ATURI, issueId int) (string, error) { 86 88 var ownerDid string 87 89 err := e.QueryRow(`select owner_did from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&ownerDid) 88 90 return ownerDid, err 89 91 } 90 92 91 - func GetIssues(e Execer, repoAt string) ([]Issue, error) { 93 + func GetIssues(e Execer, repoAt syntax.ATURI) ([]Issue, error) { 92 94 var issues []Issue 93 95 94 96 rows, err := e.Query(`select owner_did, issue_id, created, title, body, open from issues where repo_at = ? order by created desc`, repoAt) ··· 121 123 return issues, nil 122 124 } 123 125 124 - func GetIssue(e Execer, repoAt string, issueId int) (*Issue, error) { 126 + func GetIssue(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, error) { 125 127 query := `select owner_did, created, title, body, open from issues where repo_at = ? and issue_id = ?` 126 128 row := e.QueryRow(query, repoAt, issueId) 127 129 ··· 141 143 return &issue, nil 142 144 } 143 145 144 - func GetIssueWithComments(e Execer, repoAt string, issueId int) (*Issue, []Comment, error) { 146 + func GetIssueWithComments(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, []Comment, error) { 145 147 query := `select owner_did, issue_id, created, title, body, open from issues where repo_at = ? and issue_id = ?` 146 148 row := e.QueryRow(query, repoAt, issueId) 147 149 ··· 180 182 return err 181 183 } 182 184 183 - func GetComments(e Execer, repoAt string, issueId int) ([]Comment, error) { 185 + func GetComments(e Execer, repoAt syntax.ATURI, issueId int) ([]Comment, error) { 184 186 var comments []Comment 185 187 186 188 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 218 return comments, nil 217 219 } 218 220 219 - func CloseIssue(e Execer, repoAt string, issueId int) error { 221 + func CloseIssue(e Execer, repoAt syntax.ATURI, issueId int) error { 220 222 _, err := e.Exec(`update issues set open = 0 where repo_at = ? and issue_id = ?`, repoAt, issueId) 221 223 return err 222 224 } 223 225 224 - func ReopenIssue(e Execer, repoAt string, issueId int) error { 226 + func ReopenIssue(e Execer, repoAt syntax.ATURI, issueId int) error { 225 227 _, err := e.Exec(`update issues set open = 1 where repo_at = ? and issue_id = ?`, repoAt, issueId) 226 228 return err 227 229 } 230 + 231 + type IssueCount struct { 232 + Open int 233 + Closed int 234 + } 235 + 236 + func GetIssueCount(e Execer, repoAt syntax.ATURI) (IssueCount, error) { 237 + row := e.QueryRow(` 238 + select 239 + count(case when open = 1 then 1 end) as open_count, 240 + count(case when open = 0 then 1 end) as closed_count 241 + from issues 242 + where repo_at = ?`, 243 + repoAt, 244 + ) 245 + 246 + var count IssueCount 247 + if err := row.Scan(&count.Open, &count.Closed); err != nil { 248 + return IssueCount{0, 0}, err 249 + } 250 + 251 + return count, nil 252 + }
+29 -2
appview/db/repos.go
··· 14 14 AtUri string 15 15 } 16 16 17 - func GetAllRepos(e Execer) ([]Repo, error) { 17 + func GetAllRepos(e Execer, limit int) ([]Repo, error) { 18 18 var repos []Repo 19 19 20 - rows, err := e.Query(`select did, name, knot, rkey, created from repos`) 20 + rows, err := e.Query( 21 + `select did, name, knot, rkey, created 22 + from repos 23 + order by created desc 24 + limit ? 25 + `, 26 + limit, 27 + ) 21 28 if err != nil { 22 29 return nil, err 23 30 } ··· 79 86 return &repo, nil 80 87 } 81 88 89 + func GetRepoByAtUri(e Execer, atUri string) (*Repo, error) { 90 + var repo Repo 91 + 92 + row := e.QueryRow(`select did, name, knot, created, at_uri from repos where at_uri = ?`, atUri) 93 + 94 + var createdAt string 95 + if err := row.Scan(&repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.AtUri); err != nil { 96 + return nil, err 97 + } 98 + createdAtTime, _ := time.Parse(time.RFC3339, createdAt) 99 + repo.Created = createdAtTime 100 + 101 + return &repo, nil 102 + } 103 + 82 104 func AddRepo(e Execer, repo *Repo) error { 83 105 _, err := e.Exec(`insert into repos (did, name, knot, rkey, at_uri) values (?, ?, ?, ?, ?)`, repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.AtUri) 84 106 return err ··· 120 142 } 121 143 122 144 return repos, nil 145 + } 146 + 147 + type RepoStats struct { 148 + StarCount int 149 + IssueCount IssueCount 123 150 } 124 151 125 152 func scanRepo(rows *sql.Rows, did, name, knot, rkey *string, created *time.Time) error {
+150
appview/db/star.go
··· 1 + package db 2 + 3 + import ( 4 + "log" 5 + "time" 6 + 7 + "github.com/bluesky-social/indigo/atproto/syntax" 8 + ) 9 + 10 + type Star struct { 11 + StarredByDid string 12 + RepoAt syntax.ATURI 13 + Repo *Repo 14 + Created time.Time 15 + Rkey string 16 + } 17 + 18 + func (star *Star) ResolveRepo(e Execer) error { 19 + if star.Repo != nil { 20 + return nil 21 + } 22 + 23 + repo, err := GetRepoByAtUri(e, star.RepoAt.String()) 24 + if err != nil { 25 + return err 26 + } 27 + 28 + star.Repo = repo 29 + return nil 30 + } 31 + 32 + func AddStar(e Execer, starredByDid string, repoAt syntax.ATURI, rkey string) error { 33 + query := `insert or ignore into stars (starred_by_did, repo_at, rkey) values (?, ?, ?)` 34 + _, err := e.Exec(query, starredByDid, repoAt, rkey) 35 + return err 36 + } 37 + 38 + // Get a star record 39 + func GetStar(e Execer, starredByDid string, repoAt syntax.ATURI) (*Star, error) { 40 + query := ` 41 + select starred_by_did, repo_at, created, rkey 42 + from stars 43 + where starred_by_did = ? and repo_at = ?` 44 + row := e.QueryRow(query, starredByDid, repoAt) 45 + 46 + var star Star 47 + var created string 48 + err := row.Scan(&star.StarredByDid, &star.RepoAt, &created, &star.Rkey) 49 + if err != nil { 50 + return nil, err 51 + } 52 + 53 + createdAtTime, err := time.Parse(time.RFC3339, created) 54 + if err != nil { 55 + log.Println("unable to determine followed at time") 56 + star.Created = time.Now() 57 + } else { 58 + star.Created = createdAtTime 59 + } 60 + 61 + return &star, nil 62 + } 63 + 64 + // Remove a star 65 + func DeleteStar(e Execer, starredByDid string, repoAt syntax.ATURI) error { 66 + _, err := e.Exec(`delete from stars where starred_by_did = ? and repo_at = ?`, starredByDid, repoAt) 67 + return err 68 + } 69 + 70 + func GetStarCount(e Execer, repoAt syntax.ATURI) (int, error) { 71 + stars := 0 72 + err := e.QueryRow( 73 + `select count(starred_by_did) from stars where repo_at = ?`, repoAt).Scan(&stars) 74 + if err != nil { 75 + return 0, err 76 + } 77 + return stars, nil 78 + } 79 + 80 + func GetStarStatus(e Execer, userDid string, repoAt syntax.ATURI) bool { 81 + if _, err := GetStar(e, userDid, repoAt); err != nil { 82 + return false 83 + } else { 84 + return true 85 + } 86 + } 87 + 88 + func GetAllStars(e Execer, limit int) ([]Star, error) { 89 + var stars []Star 90 + 91 + rows, err := e.Query(` 92 + select 93 + s.starred_by_did, 94 + s.repo_at, 95 + s.rkey, 96 + s.created, 97 + r.did, 98 + r.name, 99 + r.knot, 100 + r.rkey, 101 + r.created, 102 + r.at_uri 103 + from stars s 104 + join repos r on s.repo_at = r.at_uri 105 + `) 106 + 107 + if err != nil { 108 + return nil, err 109 + } 110 + defer rows.Close() 111 + 112 + for rows.Next() { 113 + var star Star 114 + var repo Repo 115 + var starCreatedAt, repoCreatedAt string 116 + 117 + if err := rows.Scan( 118 + &star.StarredByDid, 119 + &star.RepoAt, 120 + &star.Rkey, 121 + &starCreatedAt, 122 + &repo.Did, 123 + &repo.Name, 124 + &repo.Knot, 125 + &repo.Rkey, 126 + &repoCreatedAt, 127 + &repo.AtUri, 128 + ); err != nil { 129 + return nil, err 130 + } 131 + 132 + star.Created, err = time.Parse(time.RFC3339, starCreatedAt) 133 + if err != nil { 134 + star.Created = time.Now() 135 + } 136 + repo.Created, err = time.Parse(time.RFC3339, repoCreatedAt) 137 + if err != nil { 138 + repo.Created = time.Now() 139 + } 140 + star.Repo = &repo 141 + 142 + stars = append(stars, star) 143 + } 144 + 145 + if err := rows.Err(); err != nil { 146 + return nil, err 147 + } 148 + 149 + return stars, nil 150 + }
+20 -6
appview/db/timeline.go
··· 8 8 type TimelineEvent struct { 9 9 *Repo 10 10 *Follow 11 + *Star 11 12 EventAt time.Time 12 13 } 13 14 15 + // TODO: this gathers heterogenous events from different sources and aggregates 16 + // them in code; if we did this entirely in sql, we could order and limit and paginate easily 14 17 func MakeTimeline(e Execer) ([]TimelineEvent, error) { 15 18 var events []TimelineEvent 19 + limit := 50 16 20 17 - repos, err := GetAllRepos(e) 21 + repos, err := GetAllRepos(e, limit) 22 + if err != nil { 23 + return nil, err 24 + } 25 + 26 + follows, err := GetAllFollows(e, limit) 18 27 if err != nil { 19 28 return nil, err 20 29 } 21 30 22 - follows, err := GetAllFollows(e) 31 + stars, err := GetAllStars(e, limit) 23 32 if err != nil { 24 33 return nil, err 25 34 } ··· 27 36 for _, repo := range repos { 28 37 events = append(events, TimelineEvent{ 29 38 Repo: &repo, 30 - Follow: nil, 31 39 EventAt: repo.Created, 32 40 }) 33 41 } 34 42 35 43 for _, follow := range follows { 36 44 events = append(events, TimelineEvent{ 37 - Repo: nil, 38 45 Follow: &follow, 39 46 EventAt: follow.FollowedAt, 40 47 }) 41 48 } 42 49 50 + for _, star := range stars { 51 + events = append(events, TimelineEvent{ 52 + Star: &star, 53 + EventAt: star.Created, 54 + }) 55 + } 56 + 43 57 sort.Slice(events, func(i, j int) bool { 44 58 return events[i].EventAt.After(events[j].EventAt) 45 59 }) 46 60 47 61 // Limit the slice to 100 events 48 - if len(events) > 50 { 49 - events = events[:50] 62 + if len(events) > limit { 63 + events = events[:limit] 50 64 } 51 65 52 66 return events, nil
+7
appview/pages/funcmap.go
··· 106 106 "markdown": func(text string) template.HTML { 107 107 return template.HTML(renderMarkdown(text)) 108 108 }, 109 + "isNil": func(t any) bool { 110 + // returns false for other "zero" values 111 + return t == nil 112 + }, 113 + "not": func(t bool) bool { 114 + return !t 115 + }, 109 116 } 110 117 }
+57 -2
appview/pages/pages.go
··· 17 17 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 18 18 "github.com/alecthomas/chroma/v2/lexers" 19 19 "github.com/alecthomas/chroma/v2/styles" 20 + "github.com/bluesky-social/indigo/atproto/syntax" 20 21 "github.com/microcosm-cc/bluemonday" 21 22 "github.com/sotangled/tangled/appview/auth" 22 23 "github.com/sotangled/tangled/appview/db" ··· 43 44 name := strings.TrimPrefix(path, "templates/") 44 45 name = strings.TrimSuffix(name, ".html") 45 46 46 - if !strings.HasPrefix(path, "templates/layouts/") { 47 + // add fragments as templates 48 + if strings.HasPrefix(path, "templates/fragments/") { 49 + tmpl, err := template.New(name). 50 + Funcs(funcMap()). 51 + ParseFS(files, path) 52 + if err != nil { 53 + return fmt.Errorf("setting up fragment: %w", err) 54 + } 55 + 56 + templates[name] = tmpl 57 + log.Printf("loaded fragment: %s", name) 58 + } 59 + 60 + // layouts and fragments are applied first 61 + if !strings.HasPrefix(path, "templates/layouts/") && 62 + !strings.HasPrefix(path, "templates/fragments/") { 47 63 // Add the page template on top of the base 48 64 tmpl, err := template.New(name). 49 65 Funcs(funcMap()). 50 - ParseFS(files, "templates/layouts/*.html", path) 66 + ParseFS(files, "templates/layouts/*.html", "templates/fragments/*.html", path) 51 67 if err != nil { 52 68 return fmt.Errorf("setting up template: %w", err) 53 69 } ··· 159 175 return p.execute("user/profile", w, params) 160 176 } 161 177 178 + type FollowFragmentParams struct { 179 + UserDid string 180 + FollowStatus db.FollowStatus 181 + } 182 + 183 + func (p *Pages) FollowFragment(w io.Writer, params FollowFragmentParams) error { 184 + return p.executePlain("fragments/follow", w, params) 185 + } 186 + 187 + type StarFragmentParams struct { 188 + IsStarred bool 189 + RepoAt syntax.ATURI 190 + Stats db.RepoStats 191 + } 192 + 193 + func (p *Pages) StarFragment(w io.Writer, params StarFragmentParams) error { 194 + return p.executePlain("fragments/star", w, params) 195 + } 196 + 162 197 type RepoInfo struct { 163 198 Name string 164 199 OwnerDid string 165 200 OwnerHandle string 166 201 Description string 202 + RepoAt syntax.ATURI 167 203 SettingsAllowed bool 204 + IsStarred bool 205 + Stats db.RepoStats 168 206 } 169 207 170 208 func (r RepoInfo) OwnerWithAt() string { ··· 191 229 } 192 230 193 231 return tabs 232 + } 233 + 234 + // each tab on a repo could have some metadata: 235 + // 236 + // issues -> number of open issues etc. 237 + // settings -> a warning icon to setup branch protection? idk 238 + // 239 + // we gather these bits of info here, because go templates 240 + // are difficult to program in 241 + func (r RepoInfo) TabMetadata() map[string]any { 242 + meta := make(map[string]any) 243 + 244 + meta["issues"] = r.Stats.IssueCount.Open 245 + 246 + // more stuff? 247 + 248 + return meta 194 249 } 195 250 196 251 type RepoIndexParams struct {
+17
appview/pages/templates/fragments/follow.html
··· 1 + {{ define "fragments/follow" }} 2 + <button id="followBtn" 3 + class="btn mt-2 w-full" 4 + 5 + {{ if eq .FollowStatus.String "IsNotFollowing" }} 6 + hx-post="/follow?subject={{.UserDid}}" 7 + {{ else }} 8 + hx-delete="/follow?subject={{.UserDid}}" 9 + {{ end }} 10 + 11 + hx-trigger="click" 12 + hx-target="#followBtn" 13 + hx-swap="outerHTML" 14 + > 15 + {{ if eq .FollowStatus.String "IsNotFollowing" }}Follow{{ else }}Unfollow{{ end }} 16 + </button> 17 + {{ end }}
+36
appview/pages/templates/fragments/star.html
··· 1 + {{ define "fragments/star" }} 2 + <button id="starBtn" 3 + class="btn text-sm disabled:opacity-50 disabled:cursor-not-allowed" 4 + 5 + {{ if .IsStarred }} 6 + hx-delete="/star?subject={{.RepoAt}}&countHint={{.Stats.StarCount}}" 7 + {{ else }} 8 + hx-post="/star?subject={{.RepoAt}}&countHint={{.Stats.StarCount}}" 9 + {{ end }} 10 + 11 + hx-trigger="click" 12 + hx-target="#starBtn" 13 + hx-swap="outerHTML" 14 + hx-disabled-elt="#starBtn" 15 + > 16 + <div class="flex gap-2 items-center"> 17 + {{ if .IsStarred }} 18 + <span class="w-3 h-3 fill-current" data-lucide="star"></span> 19 + {{ else }} 20 + <span class="w-3 h-3" data-lucide="star"></span> 21 + {{ end }} 22 + <span> 23 + {{ .Stats.StarCount }} 24 + </span> 25 + <span id="starSpinner" class="hidden"> 26 + loading 27 + </span> 28 + </div> 29 + </button> 30 + <script> 31 + document.body.addEventListener('htmx:afterRequest', function (evt) { 32 + lucide.createIcons(); 33 + }); 34 + </script> 35 + {{ end }} 36 +
+19 -11
appview/pages/templates/layouts/repobase.html
··· 2 2 3 3 {{ define "content" }} 4 4 <section id="repo-header" class="mb-4 py-2 px-6"> 5 + <div class="flex gap-3"> 5 6 <p class="text-lg"> 6 - <a href="/{{ .RepoInfo.OwnerWithAt }}">{{ .RepoInfo.OwnerWithAt }}</a> 7 - <span class="select-none">/</span> 8 - <a href="/{{ .RepoInfo.FullName }}" class="font-bold">{{ .RepoInfo.Name }}</a> 7 + <a href="/{{ .RepoInfo.OwnerWithAt }}">{{ .RepoInfo.OwnerWithAt }}</a> 8 + <span class="select-none">/</span> 9 + <a href="/{{ .RepoInfo.FullName }}" class="font-bold">{{ .RepoInfo.Name }}</a> 9 10 </p> 10 - <span> 11 - {{ if .RepoInfo.Description }} 12 - {{ .RepoInfo.Description }} 13 - {{ else }} 14 - <span class="italic">this repo has no description</span> 15 - {{ end }} 16 - </span> 11 + {{ template "fragments/star" .RepoInfo }} 12 + </div> 13 + <span> 14 + {{ if .RepoInfo.Description }} 15 + {{ .RepoInfo.Description }} 16 + {{ else }} 17 + <span class="italic">this repo has no description</span> 18 + {{ end }} 19 + </span> 17 20 </section> 18 21 <section id="repo-links" class="min-h-screen flex flex-col drop-shadow-sm"> 19 22 <nav class="w-full mx-auto ml-4"> 20 23 <div class="flex z-60"> 21 24 {{ $activeTabStyles := "-mb-px bg-white" }} 22 25 {{ $tabs := .RepoInfo.GetTabs }} 26 + {{ $tabmeta := .RepoInfo.TabMetadata }} 23 27 {{ range $item := $tabs }} 24 28 {{ $key := index $item 0 }} 25 29 {{ $value := index $item 1 }} 30 + {{ $meta := index $tabmeta $key }} 26 31 <a 27 32 href="/{{ $.RepoInfo.FullName }}{{ $value }}" 28 33 class="relative -mr-px group no-underline hover:no-underline" ··· 37 42 {{ end }} 38 43 " 39 44 > 40 - {{ $key }} 45 + {{ $key }} 46 + {{ if not (isNil $meta) }} 47 + <span class="bg-gray-200 rounded py-1/2 px-1 text-sm font-mono">{{ $meta }}</span> 48 + {{ end }} 41 49 </div> 42 50 </a> 43 51 {{ end }}
+31 -19
appview/pages/templates/timeline.html
··· 40 40 {{ range .Timeline }} 41 41 <div class="px-6 py-2 bg-white rounded drop-shadow-sm w-fit"> 42 42 {{ if .Repo }} 43 - {{ $userHandle := index $.DidHandleMap .Repo.Did }} 44 - <div class="flex items-center"> 45 - <p class="text-gray-600"> 46 - <a href="/{{ $userHandle }}" class="no-underline hover:underline">{{ $userHandle }}</a> 47 - created 48 - <a href="/{{ $userHandle }}/{{ .Repo.Name }}" class="no-underline hover:underline">{{ .Repo.Name }}</a> 49 - <time class="text-gray-700">{{ .Repo.Created | timeFmt }}</time> 50 - </p> 51 - </div> 43 + {{ $userHandle := index $.DidHandleMap .Repo.Did }} 44 + <div class="flex items-center"> 45 + <p class="text-gray-600"> 46 + <a href="/{{ $userHandle }}" class="no-underline hover:underline">{{ $userHandle }}</a> 47 + created 48 + <a href="/{{ $userHandle }}/{{ .Repo.Name }}" class="no-underline hover:underline">{{ .Repo.Name }}</a> 49 + <time class="text-gray-700">{{ .Repo.Created | timeFmt }}</time> 50 + </p> 51 + </div> 52 52 {{ else if .Follow }} 53 - {{ $userHandle := index $.DidHandleMap .Follow.UserDid }} 54 - {{ $subjectHandle := index $.DidHandleMap .Follow.SubjectDid }} 55 - <div class="flex items-center"> 56 - <p class="text-gray-600"> 57 - <a href="/{{ $userHandle }}" class="no-underline hover:underline">{{ $userHandle }}</a> 58 - followed 59 - <a href="/{{ $subjectHandle }}" class="no-underline hover:underline">{{ $subjectHandle }}</a> 60 - <time class="text-gray-700">{{ .Follow.FollowedAt | timeFmt }}</time> 61 - </p> 62 - </div> 53 + {{ $userHandle := index $.DidHandleMap .Follow.UserDid }} 54 + {{ $subjectHandle := index $.DidHandleMap .Follow.SubjectDid }} 55 + <div class="flex items-center"> 56 + <p class="text-gray-600"> 57 + <a href="/{{ $userHandle }}" class="no-underline hover:underline">{{ $userHandle }}</a> 58 + followed 59 + <a href="/{{ $subjectHandle }}" class="no-underline hover:underline">{{ $subjectHandle }}</a> 60 + <time class="text-gray-700">{{ .Follow.FollowedAt | timeFmt }}</time> 61 + </p> 62 + </div> 63 + {{ else if .Star }} 64 + {{ $starrerHandle := index $.DidHandleMap .Star.StarredByDid }} 65 + {{ $repoOwnerHandle := index $.DidHandleMap .Star.Repo.Did }} 66 + <div class="flex items-center"> 67 + <p class="text-gray-600"> 68 + <a href="/{{ $starrerHandle }}" class="no-underline hover:underline">{{ $starrerHandle }}</a> 69 + starred 70 + <a href="/{{ $repoOwnerHandle }}/{{ .Star.Repo.Name }}" class="no-underline hover:underline">{{ $repoOwnerHandle }}/{{ .Star.Repo.Name }}</a> 71 + <time class="text-gray-700">{{ .Star.Created | timeFmt }}</time> 72 + </p> 73 + </div> 63 74 {{ end }} 64 75 </div> 65 76 {{ end }} 66 77 </div> 67 78 </div> 68 79 {{ end }} 80 +
+2 -14
appview/pages/templates/user/profile.html
··· 30 30 </div> 31 31 32 32 {{ if ne .FollowStatus.String "IsSelf" }} 33 - <button id="followBtn" 34 - class="btn mt-2 w-full" 35 - {{ if eq .FollowStatus.String "IsNotFollowing" }} 36 - hx-post="/follow?subject={{.UserDid}}" 37 - {{ else }} 38 - hx-delete="/follow?subject={{.UserDid}}" 39 - {{ end }} 40 - hx-trigger="click" 41 - hx-target="#followBtn" 42 - hx-swap="outerHTML" 43 - > 44 - {{ if eq .FollowStatus.String "IsNotFollowing" }}Follow{{ else }}Unfollow{{ end }} 45 - </button> 46 - {{ end }} 33 + {{ template "fragments/follow" . }} 34 + {{ end }} 47 35 </div> 48 36 {{ end }} 49 37
+11 -22
appview/state/follow.go
··· 1 1 package state 2 2 3 3 import ( 4 - "fmt" 5 4 "log" 6 5 "net/http" 7 6 "time" ··· 10 9 lexutil "github.com/bluesky-social/indigo/lex/util" 11 10 tangled "github.com/sotangled/tangled/api/tangled" 12 11 "github.com/sotangled/tangled/appview/db" 12 + "github.com/sotangled/tangled/appview/pages" 13 13 ) 14 14 15 15 func (s *State) Follow(w http.ResponseWriter, r *http.Request) { ··· 60 60 61 61 log.Println("created atproto record: ", resp.Uri) 62 62 63 - w.Write([]byte(fmt.Sprintf(` 64 - <button id="followBtn" 65 - class="btn mt-2 w-full" 66 - hx-delete="/follow?subject=%s" 67 - hx-trigger="click" 68 - hx-target="#followBtn" 69 - hx-swap="outerHTML"> 70 - Unfollow 71 - </button> 72 - `, subjectIdent.DID.String()))) 63 + s.pages.FollowFragment(w, pages.FollowFragmentParams{ 64 + UserDid: subjectIdent.DID.String(), 65 + FollowStatus: db.IsFollowing, 66 + }) 73 67 74 68 return 75 69 case http.MethodDelete: ··· 83 77 _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{ 84 78 Collection: tangled.GraphFollowNSID, 85 79 Repo: currentUser.Did, 86 - Rkey: follow.RKey, 80 + Rkey: follow.Rkey, 87 81 }) 88 82 89 83 if err != nil { ··· 97 91 // this is not an issue, the firehose event might have already done this 98 92 } 99 93 100 - w.Write([]byte(fmt.Sprintf(` 101 - <button id="followBtn" 102 - class="btn mt-2 w-full" 103 - hx-post="/follow?subject=%s" 104 - hx-trigger="click" 105 - hx-target="#followBtn" 106 - hx-swap="outerHTML"> 107 - Follow 108 - </button> 109 - `, subjectIdent.DID.String()))) 94 + s.pages.FollowFragment(w, pages.FollowFragmentParams{ 95 + UserDid: subjectIdent.DID.String(), 96 + FollowStatus: db.IsNotFollowing, 97 + }) 98 + 110 99 return 111 100 } 112 101
+20
appview/state/jetstream.go
··· 6 6 "fmt" 7 7 "log" 8 8 9 + "github.com/bluesky-social/indigo/atproto/syntax" 9 10 "github.com/bluesky-social/jetstream/pkg/models" 10 11 tangled "github.com/sotangled/tangled/api/tangled" 11 12 "github.com/sotangled/tangled/appview/db" ··· 40 41 return err 41 42 } 42 43 err = db.AddFollow(d, did, record.Subject, e.Commit.RKey) 44 + if err != nil { 45 + return fmt.Errorf("failed to add follow to db: %w", err) 46 + } 47 + case tangled.FeedStarNSID: 48 + record := tangled.FeedStar{} 49 + err := json.Unmarshal(raw, &record) 50 + if err != nil { 51 + log.Println("invalid record") 52 + return err 53 + } 54 + 55 + subjectUri, err := syntax.ParseATURI(record.Subject) 56 + 57 + if err != nil { 58 + log.Println("invalid record") 59 + return err 60 + } 61 + 62 + err = db.AddStar(d, did, subjectUri, e.Commit.RKey) 43 63 if err != nil { 44 64 return fmt.Errorf("failed to add follow to db: %w", err) 45 65 }
+67 -89
appview/state/repo.go
··· 15 15 "time" 16 16 17 17 "github.com/bluesky-social/indigo/atproto/identity" 18 + "github.com/bluesky-social/indigo/atproto/syntax" 18 19 securejoin "github.com/cyphar/filepath-securejoin" 19 20 "github.com/go-chi/chi/v5" 20 21 "github.com/sotangled/tangled/api/tangled" ··· 75 76 76 77 user := s.auth.GetUser(r) 77 78 s.pages.RepoIndexPage(w, pages.RepoIndexParams{ 78 - LoggedInUser: user, 79 - RepoInfo: pages.RepoInfo{ 80 - OwnerDid: f.OwnerDid(), 81 - OwnerHandle: f.OwnerHandle(), 82 - Name: f.RepoName, 83 - SettingsAllowed: settingsAllowed(s, user, f), 84 - }, 79 + LoggedInUser: user, 80 + RepoInfo: f.RepoInfo(s, user), 85 81 TagMap: tagMap, 86 82 RepoIndexResponse: result, 87 83 }) ··· 126 122 127 123 user := s.auth.GetUser(r) 128 124 s.pages.RepoLog(w, pages.RepoLogParams{ 129 - LoggedInUser: user, 130 - RepoInfo: pages.RepoInfo{ 131 - OwnerDid: f.OwnerDid(), 132 - OwnerHandle: f.OwnerHandle(), 133 - Name: f.RepoName, 134 - SettingsAllowed: settingsAllowed(s, user, f), 135 - }, 125 + LoggedInUser: user, 126 + RepoInfo: f.RepoInfo(s, user), 136 127 RepoLogResponse: repolog, 137 128 }) 138 129 return ··· 167 158 168 159 user := s.auth.GetUser(r) 169 160 s.pages.RepoCommit(w, pages.RepoCommitParams{ 170 - LoggedInUser: user, 171 - RepoInfo: pages.RepoInfo{ 172 - OwnerDid: f.OwnerDid(), 173 - OwnerHandle: f.OwnerHandle(), 174 - Name: f.RepoName, 175 - SettingsAllowed: settingsAllowed(s, user, f), 176 - }, 161 + LoggedInUser: user, 162 + RepoInfo: f.RepoInfo(s, user), 177 163 RepoCommitResponse: result, 178 164 }) 179 165 return ··· 221 207 baseBlobLink := path.Join(f.OwnerDid(), f.RepoName, "blob", ref, treePath) 222 208 223 209 s.pages.RepoTree(w, pages.RepoTreeParams{ 224 - LoggedInUser: user, 225 - BreadCrumbs: breadcrumbs, 226 - BaseTreeLink: baseTreeLink, 227 - BaseBlobLink: baseBlobLink, 228 - RepoInfo: pages.RepoInfo{ 229 - OwnerDid: f.OwnerDid(), 230 - OwnerHandle: f.OwnerHandle(), 231 - Name: f.RepoName, 232 - SettingsAllowed: settingsAllowed(s, user, f), 233 - }, 210 + LoggedInUser: user, 211 + BreadCrumbs: breadcrumbs, 212 + BaseTreeLink: baseTreeLink, 213 + BaseBlobLink: baseBlobLink, 214 + RepoInfo: f.RepoInfo(s, user), 234 215 RepoTreeResponse: result, 235 216 }) 236 217 return ··· 264 245 265 246 user := s.auth.GetUser(r) 266 247 s.pages.RepoTags(w, pages.RepoTagsParams{ 267 - LoggedInUser: user, 268 - RepoInfo: pages.RepoInfo{ 269 - OwnerDid: f.OwnerDid(), 270 - OwnerHandle: f.OwnerHandle(), 271 - Name: f.RepoName, 272 - SettingsAllowed: settingsAllowed(s, user, f), 273 - }, 248 + LoggedInUser: user, 249 + RepoInfo: f.RepoInfo(s, user), 274 250 RepoTagsResponse: result, 275 251 }) 276 252 return ··· 304 280 305 281 user := s.auth.GetUser(r) 306 282 s.pages.RepoBranches(w, pages.RepoBranchesParams{ 307 - LoggedInUser: user, 308 - RepoInfo: pages.RepoInfo{ 309 - OwnerDid: f.OwnerDid(), 310 - OwnerHandle: f.OwnerHandle(), 311 - Name: f.RepoName, 312 - SettingsAllowed: settingsAllowed(s, user, f), 313 - }, 283 + LoggedInUser: user, 284 + RepoInfo: f.RepoInfo(s, user), 314 285 RepoBranchesResponse: result, 315 286 }) 316 287 return ··· 354 325 355 326 user := s.auth.GetUser(r) 356 327 s.pages.RepoBlob(w, pages.RepoBlobParams{ 357 - LoggedInUser: user, 358 - RepoInfo: pages.RepoInfo{ 359 - OwnerDid: f.OwnerDid(), 360 - OwnerHandle: f.OwnerHandle(), 361 - Name: f.RepoName, 362 - SettingsAllowed: settingsAllowed(s, user, f), 363 - }, 328 + LoggedInUser: user, 329 + RepoInfo: f.RepoInfo(s, user), 364 330 RepoBlobResponse: result, 365 331 BreadCrumbs: breadcrumbs, 366 332 }) ··· 481 447 } 482 448 483 449 s.pages.RepoSettings(w, pages.RepoSettingsParams{ 484 - LoggedInUser: user, 485 - RepoInfo: pages.RepoInfo{ 486 - OwnerDid: f.OwnerDid(), 487 - OwnerHandle: f.OwnerHandle(), 488 - Name: f.RepoName, 489 - SettingsAllowed: settingsAllowed(s, user, f), 490 - }, 450 + LoggedInUser: user, 451 + RepoInfo: f.RepoInfo(s, user), 491 452 Collaborators: repoCollaborators, 492 453 IsCollaboratorInviteAllowed: isCollaboratorInviteAllowed, 493 454 }) ··· 498 459 Knot string 499 460 OwnerId identity.Identity 500 461 RepoName string 501 - RepoAt string 462 + RepoAt syntax.ATURI 502 463 } 503 464 504 465 func (f *FullyResolvedRepo) OwnerDid() string { ··· 558 519 return collaborators, nil 559 520 } 560 521 522 + func (f *FullyResolvedRepo) RepoInfo(s *State, u *auth.User) pages.RepoInfo { 523 + isStarred := false 524 + if u != nil { 525 + isStarred = db.GetStarStatus(s.db, u.Did, syntax.ATURI(f.RepoAt)) 526 + } 527 + 528 + starCount, err := db.GetStarCount(s.db, f.RepoAt) 529 + if err != nil { 530 + log.Println("failed to get star count for ", f.RepoAt) 531 + } 532 + issueCount, err := db.GetIssueCount(s.db, f.RepoAt) 533 + if err != nil { 534 + log.Println("failed to get issue count for ", f.RepoAt) 535 + } 536 + 537 + return pages.RepoInfo{ 538 + OwnerDid: f.OwnerDid(), 539 + OwnerHandle: f.OwnerHandle(), 540 + Name: f.RepoName, 541 + RepoAt: f.RepoAt, 542 + SettingsAllowed: settingsAllowed(s, u, f), 543 + IsStarred: isStarred, 544 + Stats: db.RepoStats{ 545 + StarCount: starCount, 546 + IssueCount: issueCount, 547 + }, 548 + } 549 + } 550 + 561 551 func (s *State) RepoSingleIssue(w http.ResponseWriter, r *http.Request) { 562 552 user := s.auth.GetUser(r) 563 553 f, err := fullyResolvedRepo(r) ··· 602 592 603 593 s.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 604 594 LoggedInUser: user, 605 - RepoInfo: pages.RepoInfo{ 606 - OwnerDid: f.OwnerDid(), 607 - OwnerHandle: f.OwnerHandle(), 608 - Name: f.RepoName, 609 - SettingsAllowed: settingsAllowed(s, user, f), 610 - }, 611 - Issue: *issue, 612 - Comments: comments, 595 + RepoInfo: f.RepoInfo(s, user), 596 + Issue: *issue, 597 + Comments: comments, 613 598 614 599 IssueOwnerHandle: issueOwnerIdent.Handle.String(), 615 600 DidHandleMap: didHandleMap, ··· 770 755 return 771 756 } 772 757 758 + atUri := f.RepoAt.String() 773 759 client, _ := s.auth.AuthorizedClient(r) 774 760 _, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 775 761 Collection: tangled.RepoIssueCommentNSID, ··· 777 763 Rkey: s.TID(), 778 764 Record: &lexutil.LexiconTypeDecoder{ 779 765 Val: &tangled.RepoIssueComment{ 780 - Repo: &f.RepoAt, 766 + Repo: &atUri, 781 767 Issue: issueAt, 782 768 CommentId: &commentIdInt64, 783 769 Owner: &ownerDid, ··· 828 814 829 815 s.pages.RepoIssues(w, pages.RepoIssuesParams{ 830 816 LoggedInUser: s.auth.GetUser(r), 831 - RepoInfo: pages.RepoInfo{ 832 - OwnerDid: f.OwnerDid(), 833 - OwnerHandle: f.OwnerHandle(), 834 - Name: f.RepoName, 835 - SettingsAllowed: settingsAllowed(s, user, f), 836 - }, 817 + RepoInfo: f.RepoInfo(s, user), 837 818 Issues: issues, 838 819 DidHandleMap: didHandleMap, 839 820 }) ··· 853 834 case http.MethodGet: 854 835 s.pages.RepoNewIssue(w, pages.RepoNewIssueParams{ 855 836 LoggedInUser: user, 856 - RepoInfo: pages.RepoInfo{ 857 - Name: f.RepoName, 858 - OwnerDid: f.OwnerDid(), 859 - OwnerHandle: f.OwnerHandle(), 860 - SettingsAllowed: settingsAllowed(s, user, f), 861 - }, 837 + RepoInfo: f.RepoInfo(s, user), 862 838 }) 863 839 case http.MethodPost: 864 840 title := r.FormValue("title") ··· 895 871 } 896 872 897 873 client, _ := s.auth.AuthorizedClient(r) 874 + atUri := f.RepoAt.String() 898 875 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 899 876 Collection: tangled.RepoIssueNSID, 900 877 Repo: user.Did, 901 878 Rkey: s.TID(), 902 879 Record: &lexutil.LexiconTypeDecoder{ 903 880 Val: &tangled.RepoIssue{ 904 - Repo: f.RepoAt, 881 + Repo: atUri, 905 882 Title: title, 906 883 Body: &body, 907 884 Owner: user.Did, ··· 939 916 case http.MethodGet: 940 917 s.pages.RepoPulls(w, pages.RepoPullsParams{ 941 918 LoggedInUser: user, 942 - RepoInfo: pages.RepoInfo{ 943 - Name: f.RepoName, 944 - OwnerDid: f.OwnerDid(), 945 - OwnerHandle: f.OwnerHandle(), 946 - SettingsAllowed: settingsAllowed(s, user, f), 947 - }, 919 + RepoInfo: f.RepoInfo(s, user), 948 920 }) 949 921 } 950 922 } ··· 968 940 return nil, fmt.Errorf("malformed middleware") 969 941 } 970 942 943 + parsedRepoAt, err := syntax.ParseATURI(repoAt) 944 + if err != nil { 945 + log.Println("malformed repo at-uri") 946 + return nil, fmt.Errorf("malformed middleware") 947 + } 948 + 971 949 return &FullyResolvedRepo{ 972 950 Knot: knot, 973 951 OwnerId: id, 974 952 RepoName: repoName, 975 - RepoAt: repoAt, 953 + RepoAt: parsedRepoAt, 976 954 }, nil 977 955 } 978 956
+115
appview/state/star.go
··· 1 + package state 2 + 3 + import ( 4 + "log" 5 + "net/http" 6 + "time" 7 + 8 + comatproto "github.com/bluesky-social/indigo/api/atproto" 9 + "github.com/bluesky-social/indigo/atproto/syntax" 10 + lexutil "github.com/bluesky-social/indigo/lex/util" 11 + tangled "github.com/sotangled/tangled/api/tangled" 12 + "github.com/sotangled/tangled/appview/db" 13 + "github.com/sotangled/tangled/appview/pages" 14 + ) 15 + 16 + func (s *State) Star(w http.ResponseWriter, r *http.Request) { 17 + currentUser := s.auth.GetUser(r) 18 + 19 + subject := r.URL.Query().Get("subject") 20 + if subject == "" { 21 + log.Println("invalid form") 22 + return 23 + } 24 + 25 + subjectUri, err := syntax.ParseATURI(subject) 26 + if err != nil { 27 + log.Println("invalid form") 28 + return 29 + } 30 + 31 + client, _ := s.auth.AuthorizedClient(r) 32 + 33 + switch r.Method { 34 + case http.MethodPost: 35 + createdAt := time.Now().Format(time.RFC3339) 36 + rkey := s.TID() 37 + resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 38 + Collection: tangled.FeedStarNSID, 39 + Repo: currentUser.Did, 40 + Rkey: rkey, 41 + Record: &lexutil.LexiconTypeDecoder{ 42 + Val: &tangled.FeedStar{ 43 + Subject: subjectUri.String(), 44 + CreatedAt: createdAt, 45 + }}, 46 + }) 47 + if err != nil { 48 + log.Println("failed to create atproto record", err) 49 + return 50 + } 51 + 52 + err = db.AddStar(s.db, currentUser.Did, subjectUri, rkey) 53 + if err != nil { 54 + log.Println("failed to star", err) 55 + return 56 + } 57 + 58 + starCount, err := db.GetStarCount(s.db, subjectUri) 59 + if err != nil { 60 + log.Println("failed to get star count for ", subjectUri) 61 + } 62 + 63 + log.Println("created atproto record: ", resp.Uri) 64 + 65 + s.pages.StarFragment(w, pages.StarFragmentParams{ 66 + IsStarred: true, 67 + RepoAt: subjectUri, 68 + Stats: db.RepoStats{ 69 + StarCount: starCount, 70 + }, 71 + }) 72 + 73 + return 74 + case http.MethodDelete: 75 + // find the record in the db 76 + star, err := db.GetStar(s.db, currentUser.Did, subjectUri) 77 + if err != nil { 78 + log.Println("failed to get star relationship") 79 + return 80 + } 81 + 82 + _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{ 83 + Collection: tangled.FeedStarNSID, 84 + Repo: currentUser.Did, 85 + Rkey: star.Rkey, 86 + }) 87 + 88 + if err != nil { 89 + log.Println("failed to unstar") 90 + return 91 + } 92 + 93 + err = db.DeleteStar(s.db, currentUser.Did, subjectUri) 94 + if err != nil { 95 + log.Println("failed to delete star from DB") 96 + // this is not an issue, the firehose event might have already done this 97 + } 98 + 99 + starCount, err := db.GetStarCount(s.db, subjectUri) 100 + if err != nil { 101 + log.Println("failed to get star count for ", subjectUri) 102 + } 103 + 104 + s.pages.StarFragment(w, pages.StarFragmentParams{ 105 + IsStarred: false, 106 + RepoAt: subjectUri, 107 + Stats: db.RepoStats{ 108 + StarCount: starCount, 109 + }, 110 + }) 111 + 112 + return 113 + } 114 + 115 + }
+9 -2
appview/state/state.go
··· 184 184 didsToResolve = append(didsToResolve, ev.Repo.Did) 185 185 } 186 186 if ev.Follow != nil { 187 - didsToResolve = append(didsToResolve, ev.Follow.UserDid) 188 - didsToResolve = append(didsToResolve, ev.Follow.SubjectDid) 187 + didsToResolve = append(didsToResolve, ev.Follow.UserDid, ev.Follow.SubjectDid) 188 + } 189 + if ev.Star != nil { 190 + didsToResolve = append(didsToResolve, ev.Star.StarredByDid, ev.Star.Repo.Did) 189 191 } 190 192 } 191 193 ··· 931 933 r.With(AuthMiddleware(s)).Route("/follow", func(r chi.Router) { 932 934 r.Post("/", s.Follow) 933 935 r.Delete("/", s.Follow) 936 + }) 937 + 938 + r.With(AuthMiddleware(s)).Route("/star", func(r chi.Router) { 939 + r.Post("/", s.Star) 940 + r.Delete("/", s.Star) 934 941 }) 935 942 936 943 r.Route("/settings", func(r chi.Router) {
+6 -5
cmd/gen.go
··· 14 14 if err := genCfg.WriteMapEncodersToFile( 15 15 "api/tangled/cbor_gen.go", 16 16 "tangled", 17 + shtangled.FeedStar{}, 18 + shtangled.GraphFollow{}, 19 + shtangled.KnotMember{}, 17 20 shtangled.PublicKey{}, 18 - shtangled.KnotMember{}, 19 - shtangled.GraphFollow{}, 21 + shtangled.RepoIssueComment{}, 22 + shtangled.RepoIssueState{}, 23 + shtangled.RepoIssue{}, 20 24 shtangled.Repo{}, 21 - shtangled.RepoIssue{}, 22 - shtangled.RepoIssueState{}, 23 - shtangled.RepoIssueComment{}, 24 25 ); err != nil { 25 26 panic(err) 26 27 }
+31
lexicons/star.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.tangled.feed.star", 4 + "needsCbor": true, 5 + "needsType": true, 6 + "defs": { 7 + "main": { 8 + "type": "record", 9 + "key": "tid", 10 + "record": { 11 + "type": "object", 12 + "required": [ 13 + "createdAt", 14 + "subject" 15 + ], 16 + "properties": { 17 + "createdAt": { 18 + "type": "string", 19 + "format": "datetime" 20 + }, 21 + "subject": { 22 + "type": "string", 23 + "format": "at-uri" 24 + } 25 + } 26 + } 27 + } 28 + } 29 + } 30 + 31 +