diff options
Diffstat (limited to 'mastoapi.c')
| -rw-r--r-- | mastoapi.c | 343 |
1 files changed, 177 insertions, 166 deletions
| @@ -403,7 +403,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 403 | xs_str *mastoapi_id(const xs_dict *msg) | 403 | xs_str *mastoapi_id(const xs_dict *msg) |
| 404 | /* returns a somewhat Mastodon-compatible status id */ | 404 | /* returns a somewhat Mastodon-compatible status id */ |
| 405 | { | 405 | { |
| 406 | char tmp[256] = ""; | 406 | char tmp[15] = ""; |
| 407 | int n = 0; | 407 | int n = 0; |
| 408 | const char *id = xs_dict_get(msg, "id"); | 408 | const char *id = xs_dict_get(msg, "id"); |
| 409 | const char *published = xs_dict_get(msg, "published"); | 409 | const char *published = xs_dict_get(msg, "published"); |
| @@ -424,6 +424,178 @@ xs_str *mastoapi_id(const xs_dict *msg) | |||
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | 426 | ||
| 427 | xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) | ||
| 428 | /* converts an ActivityPub note to a Mastodon status */ | ||
| 429 | { | ||
| 430 | xs *actor = NULL; | ||
| 431 | actor_get(snac, xs_dict_get(msg, "attributedTo"), &actor); | ||
| 432 | |||
| 433 | /* if the author is not here, discard */ | ||
| 434 | if (actor == NULL) | ||
| 435 | return NULL; | ||
| 436 | |||
| 437 | /** shave the yak converting an ActivityPub Note to a Mastodon status **/ | ||
| 438 | |||
| 439 | xs *acct = xs_dict_new(); | ||
| 440 | |||
| 441 | const char *display_name = xs_dict_get(actor, "name"); | ||
| 442 | if (xs_is_null(display_name) || *display_name == '\0') | ||
| 443 | display_name = xs_dict_get(actor, "preferredUsername"); | ||
| 444 | |||
| 445 | const char *id = xs_dict_get(actor, "id"); | ||
| 446 | const char *pub = xs_dict_get(actor, "published"); | ||
| 447 | xs *acct_md5 = xs_md5_hex(id, strlen(id)); | ||
| 448 | acct = xs_dict_append(acct, "id", acct_md5); | ||
| 449 | acct = xs_dict_append(acct, "username", xs_dict_get(actor, "preferredUsername")); | ||
| 450 | acct = xs_dict_append(acct, "acct", xs_dict_get(actor, "preferredUsername")); | ||
| 451 | acct = xs_dict_append(acct, "display_name", display_name); | ||
| 452 | |||
| 453 | if (pub) | ||
| 454 | acct = xs_dict_append(acct, "created_at", pub); | ||
| 455 | |||
| 456 | acct = xs_dict_append(acct, "note", xs_dict_get(actor, "summary")); | ||
| 457 | acct = xs_dict_append(acct, "url", id); | ||
| 458 | |||
| 459 | xs *avatar = NULL; | ||
| 460 | xs_dict *av = xs_dict_get(actor, "icon"); | ||
| 461 | |||
| 462 | if (xs_type(av) == XSTYPE_DICT) | ||
| 463 | avatar = xs_dup(xs_dict_get(av, "url")); | ||
| 464 | else | ||
| 465 | avatar = xs_fmt("%s/susie.png", srv_baseurl); | ||
| 466 | |||
| 467 | acct = xs_dict_append(acct, "avatar", avatar); | ||
| 468 | |||
| 469 | xs *f = xs_val_new(XSTYPE_FALSE); | ||
| 470 | xs *t = xs_val_new(XSTYPE_TRUE); | ||
| 471 | xs *n = xs_val_new(XSTYPE_NULL); | ||
| 472 | xs *el = xs_list_new(); | ||
| 473 | xs *idx = NULL; | ||
| 474 | xs *ixc = NULL; | ||
| 475 | |||
| 476 | char *tmp; | ||
| 477 | id = xs_dict_get(msg, "id"); | ||
| 478 | xs *mid = mastoapi_id(msg); | ||
| 479 | |||
| 480 | xs_dict *st = xs_dict_new(); | ||
| 481 | |||
| 482 | st = xs_dict_append(st, "id", mid); | ||
| 483 | st = xs_dict_append(st, "uri", id); | ||
| 484 | st = xs_dict_append(st, "url", id); | ||
| 485 | st = xs_dict_append(st, "created_at", xs_dict_get(msg, "published")); | ||
| 486 | st = xs_dict_append(st, "account", acct); | ||
| 487 | st = xs_dict_append(st, "content", xs_dict_get(msg, "content")); | ||
| 488 | |||
| 489 | st = xs_dict_append(st, "visibility", | ||
| 490 | is_msg_public(snac, msg) ? "public" : "private"); | ||
| 491 | |||
| 492 | tmp = xs_dict_get(msg, "sensitive"); | ||
| 493 | if (xs_is_null(tmp)) | ||
| 494 | tmp = f; | ||
| 495 | |||
| 496 | st = xs_dict_append(st, "sensitive", tmp); | ||
| 497 | |||
| 498 | tmp = xs_dict_get(msg, "summary"); | ||
| 499 | if (xs_is_null(tmp)) | ||
| 500 | tmp = ""; | ||
| 501 | |||
| 502 | st = xs_dict_append(st, "spoiler_text", tmp); | ||
| 503 | |||
| 504 | /* create the list of attachments */ | ||
| 505 | xs *matt = xs_list_new(); | ||
| 506 | xs_list *att = xs_dict_get(msg, "attachment"); | ||
| 507 | xs_str *aobj; | ||
| 508 | |||
| 509 | while (xs_list_iter(&att, &aobj)) { | ||
| 510 | const char *mtype = xs_dict_get(aobj, "mediaType"); | ||
| 511 | |||
| 512 | if (!xs_is_null(mtype) && xs_startswith(mtype, "image/")) { | ||
| 513 | xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt)); | ||
| 514 | xs *matte = xs_dict_new(); | ||
| 515 | |||
| 516 | matte = xs_dict_append(matte, "id", matteid); | ||
| 517 | matte = xs_dict_append(matte, "type", "image"); | ||
| 518 | matte = xs_dict_append(matte, "url", xs_dict_get(aobj, "url")); | ||
| 519 | matte = xs_dict_append(matte, "preview_url", xs_dict_get(aobj, "url")); | ||
| 520 | matte = xs_dict_append(matte, "remote_url", xs_dict_get(aobj, "url")); | ||
| 521 | matte = xs_dict_append(matte, "description", xs_dict_get(aobj, "name")); | ||
| 522 | |||
| 523 | matt = xs_list_append(matt, matte); | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 527 | st = xs_dict_append(st, "media_attachments", matt); | ||
| 528 | |||
| 529 | st = xs_dict_append(st, "mentions", el); | ||
| 530 | st = xs_dict_append(st, "tags", el); | ||
| 531 | st = xs_dict_append(st, "emojis", el); | ||
| 532 | |||
| 533 | xs_free(idx); | ||
| 534 | xs_free(ixc); | ||
| 535 | idx = object_likes(id); | ||
| 536 | ixc = xs_number_new(xs_list_len(idx)); | ||
| 537 | |||
| 538 | st = xs_dict_append(st, "favourites_count", ixc); | ||
| 539 | st = xs_dict_append(st, "favourited", | ||
| 540 | xs_list_in(idx, snac->md5) != -1 ? t : f); | ||
| 541 | |||
| 542 | xs_free(idx); | ||
| 543 | xs_free(ixc); | ||
| 544 | idx = object_announces(id); | ||
| 545 | ixc = xs_number_new(xs_list_len(idx)); | ||
| 546 | |||
| 547 | st = xs_dict_append(st, "reblogs_count", ixc); | ||
| 548 | st = xs_dict_append(st, "reblogged", | ||
| 549 | xs_list_in(idx, snac->md5) != -1 ? t : f); | ||
| 550 | |||
| 551 | xs_free(idx); | ||
| 552 | xs_free(ixc); | ||
| 553 | idx = object_children(id); | ||
| 554 | ixc = xs_number_new(xs_list_len(idx)); | ||
| 555 | |||
| 556 | st = xs_dict_append(st, "replies_count", ixc); | ||
| 557 | |||
| 558 | /* default in_reply_to values */ | ||
| 559 | st = xs_dict_append(st, "in_reply_to_id", n); | ||
| 560 | st = xs_dict_append(st, "in_reply_to_account_id", n); | ||
| 561 | |||
| 562 | tmp = xs_dict_get(msg, "inReplyTo"); | ||
| 563 | if (!xs_is_null(tmp)) { | ||
| 564 | xs *irto = NULL; | ||
| 565 | |||
| 566 | if (valid_status(object_get(tmp, &irto))) { | ||
| 567 | xs *irt_mid = mastoapi_id(irto); | ||
| 568 | st = xs_dict_set(st, "in_reply_to_id", irt_mid); | ||
| 569 | |||
| 570 | char *at = NULL; | ||
| 571 | if (!xs_is_null(at = xs_dict_get(irto, "attributedTo"))) { | ||
| 572 | xs *at_md5 = xs_md5_hex(at, strlen(at)); | ||
| 573 | st = xs_dict_set(st, "in_reply_to_account_id", at_md5); | ||
| 574 | } | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | st = xs_dict_append(st, "reblog", n); | ||
| 579 | st = xs_dict_append(st, "poll", n); | ||
| 580 | st = xs_dict_append(st, "card", n); | ||
| 581 | st = xs_dict_append(st, "language", n); | ||
| 582 | |||
| 583 | tmp = xs_dict_get(msg, "sourceContent"); | ||
| 584 | if (xs_is_null(tmp)) | ||
| 585 | tmp = ""; | ||
| 586 | |||
| 587 | st = xs_dict_append(st, "text", tmp); | ||
| 588 | |||
| 589 | tmp = xs_dict_get(msg, "updated"); | ||
| 590 | if (xs_is_null(tmp)) | ||
| 591 | tmp = n; | ||
| 592 | |||
| 593 | st = xs_dict_append(st, "edited_at", tmp); | ||
| 594 | |||
| 595 | return st; | ||
| 596 | } | ||
| 597 | |||
| 598 | |||
| 427 | int mastoapi_get_handler(const xs_dict *req, const char *q_path, | 599 | int mastoapi_get_handler(const xs_dict *req, const char *q_path, |
| 428 | char **body, int *b_size, char **ctype) | 600 | char **body, int *b_size, char **ctype) |
| 429 | { | 601 | { |
| @@ -548,172 +720,11 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 548 | if (strcmp(xs_dict_get(msg, "type"), "Note") != 0) | 720 | if (strcmp(xs_dict_get(msg, "type"), "Note") != 0) |
| 549 | continue; | 721 | continue; |
| 550 | 722 | ||
| 551 | xs *actor = NULL; | 723 | /* convert the Note into a Mastodon status */ |
| 552 | actor_get(&snac, xs_dict_get(msg, "attributedTo"), &actor); | 724 | xs *st = mastoapi_status(&snac, msg); |
| 553 | |||
| 554 | /* if the author is not here, discard */ | ||
| 555 | if (actor == NULL) | ||
| 556 | continue; | ||
| 557 | |||
| 558 | /** shave the yak converting an ActivityPub Note to a Mastodon status **/ | ||
| 559 | |||
| 560 | xs *acct = xs_dict_new(); | ||
| 561 | |||
| 562 | const char *display_name = xs_dict_get(actor, "name"); | ||
| 563 | if (xs_is_null(display_name) || *display_name == '\0') | ||
| 564 | display_name = xs_dict_get(actor, "preferredUsername"); | ||
| 565 | |||
| 566 | const char *id = xs_dict_get(actor, "id"); | ||
| 567 | const char *pub = xs_dict_get(actor, "published"); | ||
| 568 | xs *acct_md5 = xs_md5_hex(id, strlen(id)); | ||
| 569 | acct = xs_dict_append(acct, "id", acct_md5); | ||
| 570 | acct = xs_dict_append(acct, "username", xs_dict_get(actor, "preferredUsername")); | ||
| 571 | acct = xs_dict_append(acct, "acct", xs_dict_get(actor, "preferredUsername")); | ||
| 572 | acct = xs_dict_append(acct, "display_name", display_name); | ||
| 573 | |||
| 574 | if (pub) | ||
| 575 | acct = xs_dict_append(acct, "created_at", pub); | ||
| 576 | |||
| 577 | acct = xs_dict_append(acct, "note", xs_dict_get(actor, "summary")); | ||
| 578 | acct = xs_dict_append(acct, "url", id); | ||
| 579 | |||
| 580 | xs *avatar = NULL; | ||
| 581 | xs_dict *av = xs_dict_get(actor, "icon"); | ||
| 582 | |||
| 583 | if (xs_type(av) == XSTYPE_DICT) | ||
| 584 | avatar = xs_dup(xs_dict_get(av, "url")); | ||
| 585 | else | ||
| 586 | avatar = xs_fmt("%s/susie.png", srv_baseurl); | ||
| 587 | |||
| 588 | acct = xs_dict_append(acct, "avatar", avatar); | ||
| 589 | |||
| 590 | xs *f = xs_val_new(XSTYPE_FALSE); | ||
| 591 | xs *t = xs_val_new(XSTYPE_TRUE); | ||
| 592 | xs *n = xs_val_new(XSTYPE_NULL); | ||
| 593 | xs *el = xs_list_new(); | ||
| 594 | xs *idx = NULL; | ||
| 595 | xs *ixc = NULL; | ||
| 596 | |||
| 597 | char *tmp; | ||
| 598 | id = xs_dict_get(msg, "id"); | ||
| 599 | xs *mid = mastoapi_id(msg); | ||
| 600 | |||
| 601 | xs *st = xs_dict_new(); | ||
| 602 | |||
| 603 | st = xs_dict_append(st, "id", mid); | ||
| 604 | st = xs_dict_append(st, "uri", id); | ||
| 605 | st = xs_dict_append(st, "url", id); | ||
| 606 | st = xs_dict_append(st, "created_at", xs_dict_get(msg, "published")); | ||
| 607 | st = xs_dict_append(st, "account", acct); | ||
| 608 | st = xs_dict_append(st, "content", xs_dict_get(msg, "content")); | ||
| 609 | |||
| 610 | st = xs_dict_append(st, "visibility", | ||
| 611 | is_msg_public(&snac, msg) ? "public" : "private"); | ||
| 612 | |||
| 613 | tmp = xs_dict_get(msg, "sensitive"); | ||
| 614 | if (xs_is_null(tmp)) | ||
| 615 | tmp = f; | ||
| 616 | |||
| 617 | st = xs_dict_append(st, "sensitive", tmp); | ||
| 618 | |||
| 619 | tmp = xs_dict_get(msg, "summary"); | ||
| 620 | if (xs_is_null(tmp)) | ||
| 621 | tmp = ""; | ||
| 622 | |||
| 623 | st = xs_dict_append(st, "spoiler_text", tmp); | ||
| 624 | |||
| 625 | /* create the list of attachments */ | ||
| 626 | xs *matt = xs_list_new(); | ||
| 627 | xs_list *att = xs_dict_get(msg, "attachment"); | ||
| 628 | xs_str *aobj; | ||
| 629 | |||
| 630 | while (xs_list_iter(&att, &aobj)) { | ||
| 631 | const char *mtype = xs_dict_get(aobj, "mediaType"); | ||
| 632 | |||
| 633 | if (!xs_is_null(mtype) && xs_startswith(mtype, "image/")) { | ||
| 634 | xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt)); | ||
| 635 | xs *matte = xs_dict_new(); | ||
| 636 | |||
| 637 | matte = xs_dict_append(matte, "id", matteid); | ||
| 638 | matte = xs_dict_append(matte, "type", "image"); | ||
| 639 | matte = xs_dict_append(matte, "url", xs_dict_get(aobj, "url")); | ||
| 640 | matte = xs_dict_append(matte, "preview_url", xs_dict_get(aobj, "url")); | ||
| 641 | matte = xs_dict_append(matte, "remote_url", xs_dict_get(aobj, "url")); | ||
| 642 | matte = xs_dict_append(matte, "description", xs_dict_get(aobj, "name")); | ||
| 643 | |||
| 644 | matt = xs_list_append(matt, matte); | ||
| 645 | } | ||
| 646 | } | ||
| 647 | |||
| 648 | st = xs_dict_append(st, "media_attachments", matt); | ||
| 649 | |||
| 650 | st = xs_dict_append(st, "mentions", el); | ||
| 651 | st = xs_dict_append(st, "tags", el); | ||
| 652 | st = xs_dict_append(st, "emojis", el); | ||
| 653 | |||
| 654 | xs_free(idx); | ||
| 655 | xs_free(ixc); | ||
| 656 | idx = object_likes(id); | ||
| 657 | ixc = xs_number_new(xs_list_len(idx)); | ||
| 658 | |||
| 659 | st = xs_dict_append(st, "favourites_count", ixc); | ||
| 660 | st = xs_dict_append(st, "favourited", | ||
| 661 | xs_list_in(idx, snac.md5) != -1 ? t : f); | ||
| 662 | |||
| 663 | xs_free(idx); | ||
| 664 | xs_free(ixc); | ||
| 665 | idx = object_announces(id); | ||
| 666 | ixc = xs_number_new(xs_list_len(idx)); | ||
| 667 | |||
| 668 | st = xs_dict_append(st, "reblogs_count", ixc); | ||
| 669 | st = xs_dict_append(st, "reblogged", | ||
| 670 | xs_list_in(idx, snac.md5) != -1 ? t : f); | ||
| 671 | |||
| 672 | xs_free(idx); | ||
| 673 | xs_free(ixc); | ||
| 674 | idx = object_children(id); | ||
| 675 | ixc = xs_number_new(xs_list_len(idx)); | ||
| 676 | |||
| 677 | st = xs_dict_append(st, "replies_count", ixc); | ||
| 678 | |||
| 679 | /* default in_reply_to values */ | ||
| 680 | st = xs_dict_append(st, "in_reply_to_id", n); | ||
| 681 | st = xs_dict_append(st, "in_reply_to_account_id", n); | ||
| 682 | |||
| 683 | tmp = xs_dict_get(msg, "inReplyTo"); | ||
| 684 | if (!xs_is_null(tmp)) { | ||
| 685 | xs *irto = NULL; | ||
| 686 | |||
| 687 | if (valid_status(object_get(tmp, &irto))) { | ||
| 688 | xs *irt_mid = mastoapi_id(irto); | ||
| 689 | st = xs_dict_set(st, "in_reply_to_id", irt_mid); | ||
| 690 | |||
| 691 | char *at = NULL; | ||
| 692 | if (!xs_is_null(at = xs_dict_get(irto, "attributedTo"))) { | ||
| 693 | xs *at_md5 = xs_md5_hex(at, strlen(at)); | ||
| 694 | st = xs_dict_set(st, "in_reply_to_account_id", at_md5); | ||
| 695 | } | ||
| 696 | } | ||
| 697 | } | ||
| 698 | |||
| 699 | st = xs_dict_append(st, "reblog", n); | ||
| 700 | st = xs_dict_append(st, "poll", n); | ||
| 701 | st = xs_dict_append(st, "card", n); | ||
| 702 | st = xs_dict_append(st, "language", n); | ||
| 703 | |||
| 704 | tmp = xs_dict_get(msg, "sourceContent"); | ||
| 705 | if (xs_is_null(tmp)) | ||
| 706 | tmp = ""; | ||
| 707 | |||
| 708 | st = xs_dict_append(st, "text", tmp); | ||
| 709 | |||
| 710 | tmp = xs_dict_get(msg, "updated"); | ||
| 711 | if (xs_is_null(tmp)) | ||
| 712 | tmp = n; | ||
| 713 | |||
| 714 | st = xs_dict_append(st, "edited_at", tmp); | ||
| 715 | 725 | ||
| 716 | out = xs_list_append(out, st); | 726 | if (st != NULL) |
| 727 | out = xs_list_append(out, st); | ||
| 717 | 728 | ||
| 718 | cnt++; | 729 | cnt++; |
| 719 | } | 730 | } |